The JNA (Java Native access) Framework is an open-source Java framework developed by Sun and built on the basis of the classic JNI. Using JNI to call shared class libraries (. dll/. So files) is very troublesome.CodeC language proxy method, which requires a lot of data type conversion, is a headache. The JNA framework is developed to solve these problems and complex tasks. It provides a set of Java tool classes for dynamic access to the local shared class libraries of the system at runtime without the need to write any native/JNI code. As long as developers describe the functions and structure of the target native library in a Java interface, JNA will automatically map the Java interface to the native function, this greatly reduces the difficulty of developing Java-called ontology shared libraries. JNA is as simple and convenient as the P/invoke mechanism on the. NET platform.
You only need to download a jar package and use the powerful functions of JNA to conveniently call the C function in the dynamic link library. Yes: https://github.com/twall/jna
JNA calls local library functions
Suppose there is a dynamic link library: cnblogsjna. dll. There is such a function:
VoidSayhello (Char*Name) {printf ("C code start... \ n"); Printf ("Hello! Mr % S. \ n", Name); printf ("C code end. \ n");}
This function receives a character pointer representing the name, and then outputs several strings on the console.
To call this function and use JNA, We need to write the following Java code:
1. Interface icnblogsjna. Java
Import Com. Sun. JNA. Library; Import Com. Sun. JNA. Native; /** * @ Author BCH) Wang guocheng */ Public Interface Icnblogsjna Extends Library { // Interface instance Icnblogsjna instance = (icnblogsjna) Native. loadlibrary ("cnblogsjna", icnblogsjna.Class ); // Functions mapped to C code Public Void Sayhello (string name );}
Note: The interface must inherit the JNA library interface;
An internal public static constant instance is required for the interface. Through this constant, the instance of this interface can be obtained to use the interface method. That is, the sayhello function in the dynamic link library cnblogsjna. dll is called.
If you use JNI, you need to use the system. loadlibrary method to load the dynamic link library we have compiled for JNI. This dynamic link library is actually the proxy of the dynamic link library we actually need. To use JNA, we need to use the native class loadlibrary function of the JNA class library to directly load the dynamic link library we need. When using JNA, we do not need to write a dynamic link library as a proxy or a line of native code.
The loadlibrary method of the native class has two parameters: the first parameter is the name of the. dll or. So file, without the suffix. This complies with the JNI specification, because it cannot be used across operating system platforms with the suffix. The second parameter is the class type of this interface. Through this class type, JNA dynamically creates an interface instance based on the specified dll/. So file.
2. Java method for calling functions in the dynamic link library file ():
/** * @ author BCH) wang guocheng */ Public class cnblogsjna { /** * entry function * @ Param ARGs */ Public static void main (string [] ARGs) { // call the sayhello function in the dynamic link library icnblogsjna. instance. sayhello ("wanggc/Wang guocheng" ) ;}
The method is simple, just like calling a Java function. The output result is as follows:
Type ing with native code
Cross-platform and cross-language calls are caused by inconsistent data types between different languages. JNA is no exception. To call cross-platform calls, data type conversion is unavoidable. JNA provides type ing between Java and native code.
The corresponding tables of Java and C data types are as follows:
JavaClassType |
CClassType |
Native tableNow |
Boolean |
Int |
32-bit integer (customizable) |
Byte |
Char |
8-digit integer |
Char |
Wchar_t |
Platform dependency |
Short |
Short |
16-digit integer |
Int |
Int |
32-bit integer |
Long |
Long long, _ int64 |
64-bit integer |
Float |
Float |
32-bit floating point number |
Double |
Double |
64-bit floating point number |
Buffer/pointer |
Pointer |
Platform dependency (32 or 64-bit pointer) |
<T> [] (basic type array) |
Pointer/Array |
32 or 64-bit pointer (parameter/return value) Adjacent memory (struct) |
String |
Char * |
/0 end array (native encoding or JNA. Encoding) |
Wstring |
Wchar_t * |
/0 end array (UNICODE) |
String [] |
Char ** |
/0 end Array |
Wstring [] |
Wchar_t ** |
/0 end wide character array Array |
Structure |
Struct */struct |
Pointer to the struct (parameter or return value) (or explicitly specifying the struct pointer) Struct (a member of the struct) (or explicitly specifying a struct) |
Union |
Union |
Equivalent to struct |
Structure [] |
Struct [] |
Struct array, adjacent to memory |
Callback |
<T> (* FP )() |
Java function pointer or native function pointer |
Nativemapped |
Varies |
Dependency on Definition |
Nativelong |
Long |
Platform dependency (32 or 64-bit integer) |
Pointertype |
Pointer |
Same as pointer |
cross-platform and cross-language data transmission is as few as possible because it cannot be overcome. If this is required, try to use a simple data type. If a complex data type needs to be passed in Java and native functions, we must simulate this complex native type in Java. This will greatly increase the difficulty of implementation, and even cannot be achieved. If a large amount of data is transmitted between Java and native functions, on the one hand, the performance of the Program is lost, and on the other hand, memory fragmentation occurs, when Java calls a native function, it will fix the data in the memory so that the native function can access the Java data. The GC of JVM cannot be managed, which may cause memory fragmentation.