It’s possible with help of Memory and Pointer JNA objects. Example covering such case is provided in my another article: How to call/invoke external DLL library method/function from Java code?
Archive for the ‘Java’ Category
How to call/invoke external DLL library method/function from Java code?
Introduction
Java’s JVM allows you to do many smart things but sometimes you may be forced to directly use external library or writing code in pure java would be very time-consuming comparing it with something more low-leveled. I stumbled upon such a problem and had to use a .dll driver from a hardware provider. Of course I googled it and didn’t find much info, and what I’ve found mostly concerned about JNI (Java Native Interface). I would like to tell you about JNA which is fast and simple to use in aforementioned task.
Java code:
package jnahelloworldtest; import com.sun.jna.Library; import com.sun.jna.Native; import com.sun.jna.NativeLong; import com.sun.jna.Platform; import com.sun.jna.*; /** Simple example of native library declaration and usage. */ public class Main { public interface simpleDLL extends Library { simpleDLL INSTANCE = (simpleDLL) Native.loadLibrary( (Platform.isWindows() ? "simpleDLL" : "simpleDLLLinuxPort"), simpleDLL.class); // it's possible to check the platform on which program runs, for example purposes we assume that there's a linux port of the library (it's not attached to the downloadable project) byte giveVoidPtrGetChar(Pointer param); // char giveVoidPtrGetChar(void* param); int giveVoidPtrGetInt(Pointer param); //int giveVoidPtrGetInt(void* param); int giveIntGetInt(int a); // int giveIntGetInt(int a); void simpleCall(); // void simpleCall(); } public static void main(String[] args) { simpleDLL sdll = simpleDLL.INSTANCE; sdll.simpleCall(); // call of void function int a = 3; int result1 = sdll.giveIntGetInt(a); // calling function with int parameter&result System.out.println("giveIntGetInt("+a+"): " + result1); String testStr = "ToBeOrNotToBe"; Memory mTest = new Memory(testStr.length()+1); // '+1' remember about extra byte for \0 character! mTest.setString(0, testStr); String testReturn = mTest.getString(0); // you can see that String got properly stored in Memory object System.out.println("String in Memory:"+testReturn); Memory intMem = new Memory(4); // allocating space intMem.setInt(0, 666); // setting allocated memory to an integer Pointer intPointer = intMem.getPointer(0); int int1 = sdll.giveVoidPtrGetInt(Pointer.NULL); // passing null, getting default result System.out.println("giveVoidPtrGetInt(null):" + int1); // passing int stored in Memory object, getting it back int int2 = sdll.giveVoidPtrGetInt(intMem); //int int2 = sdll.giveVoidPtrGetInt(intPointer); causes JVM crash, use memory object directly! System.out.println("giveVoidPtrGetInt(666):" + int2); byte char1 = sdll.giveVoidPtrGetChar(Pointer.NULL); // passing null, getting default result byte char2 = sdll.giveVoidPtrGetChar(mTest); // passing string stored in Memory object, getting first letter System.out.println("giveVoidPtrGetChar(null):" + (char)char1); System.out.println("giveVoidPtrGetChar('ToBeOrNotToBe'):" + (char)char2); } }
Mappings table
Not every native type maps directly to Java type, furthermore a class representing pointers had to be introduced. You can read a handy type mapping table below:
Native Type | Size | Java Language Type | Common Windows Types |
---|---|---|---|
char | 8-bit integer | byte | BYTE, TCHAR |
short | 16-bit | short | short WORD |
wchar_t | 16/32-bit character | char | WCHAR, TCHAR |
int | 32-bit integer | int | DWORD |
int | boolean value | boolean | BOOL |
long | 32/64-bit integer | NativeLong | LONG |
long long, __int64 | 64-bit integer | long | |
float | 32-bit FP | float | |
double | 64-bit FP | double | |
char* | C string | String | LPTCSTR |
void* | pointer | Pointer | LPVOID, HANDLE, LPXXX |
Downloads:
- DLLVisual Studio source project – ready to use Visual Studio 2010 project. You can alter it to continue experimenting with invoking DLL methods of library attached to the Netbeans project.
- Netbeans project – ready to use NetBeans 6 project using example code explained in this article with appropriate jars and DLL library attached
- JNA library jars – link to official JNA libraries download page
Useful links:
- An article about using JNA and windows kernel library (eg. checking state of joystick)
- JNA project home page. You can find JavaDoc FAQ and other documentation here
DLL library C++ functions source :
#include "simpleDLL.h" #include <stdexcept> using namespace std; namespace simpleDLLNS { char simpleDLL::giveVoidPtrGetChar(void* param) { if(param != 0) { char* paramChrPtr = (char*)param; return *paramChrPtr; } else { return 'x'; } } int simpleDLL::giveIntGetInt(int a) { return 2*a; } void simpleDLL::simpleCall(void) { int x = 3; return; } int simpleDLL::giveVoidPtrGetInt(void* param) { if(param!=0) { int* x = (int*)param; return *x; } else { return -1; } } }
How to properly run java console application with a doubleclick (Windows)
You’ve developed a java application which runs fine in your IDE but now you want to show your application to the outer world. Running a java program by setting up windows command window and then typing java -jar myProgram.jar paramA paramB .. may be a bit confusing for an everyday user, so the simplier means to do it are quite desirable.
A simple way to achieve this is to use a batch (.bat) file.
Let’s assume you have a console java application which takes one parameter – a configuration filepath and name. You can create a simple script file which will run this application in console for you after a doubleclick.
You should:
1. Create a text file like this :
@echo off set jarpath="JavaApp.jar" java -jar %jarpath% %CD%\Config.txt PAUSE
%CD% is a pseudo-variable which holds the working directory. It’s useful when you eg. want to load a config file located in the same folder as your .bat file.
PAUSE displays a localized version of “Press any key to continue…” message.
2. Save it as .bat file.
3. The program is ready for double click run!
I get NoClassDefFoundError after refactor (rename) in NetBeans although there are no errors in my code
If you’re really sure that you didn’t do any error (such as mistypo) clearing NetBeans cache folder may help. It’s located in the following directory:
“<user home>\.netbeans\<version>\var\cache”
Close NetBeans before doing this.
How to send data from OutputStream to a String in Java?
ByteArrayOutputStream os = new ByteArrayOutputStream(); aClass.outputStreamMethod(os); String aString = new String(os.toByteArray(),"UTF-8");