1. JNA Brief Introduction
Let's start with the JNI (Java Native Interface), which has the experience of communicating between different languages, which allows Java code to interact with code written in other languages, especially C/C + +, as long as the calling convention is adhered to. First look at the JNI process of calling C + +, note that the program is written from bottom to top.
The visible steps are very much, very cumbersome, and are called using JNI. dll/.so Shared library can experience this painful process. If you already have a compiled. dll/.so file, if you use the JNI technology call, we first need to write another in the C language. Dll/.so shared library, using the sun-defined data structure instead of the C language, calls functions advertised in the existing dll/so. Then load the library dll/so in Java, and finally write the Java native function as the proxy for the function in the link library. These tedious steps are required to invoke native code in Java. Therefore, few Java programmers are willing to write Java programs that invoke native functions in the dll/.so library. This also makes the Java language on the client side, can be said that JNI is a major weakness of Java!
So what is JNA?
JNA (Java Native Access) is an open-source Java framework, a technology that Sun has launched to invoke local methods, a framework built on the classic JNI Foundation. The reason for this is that it is a JNI alternative because JNA greatly simplifies the process of invoking local methods, which is easy to use and does not need to be done without leaving the Java environment.
If you want to compare it, then the process of JNA calling C + + is roughly the following:
You can see that the steps are reduced a lot, and most importantly, we don't need to rewrite our dynamic link library files, but we have a direct call API, which greatly simplifies our workload.
JNA only requires us to write Java code without having to write JNI or local code. Features are relative to Windows Platform/invoke and Python ctypes.
2. JNA Technical principle
JNA uses a small JNI library plug-in program to dynamically invoke local code. Developers use the Java interface to describe the functionality and structure of the target local library, making it easy to take advantage of the functionality of native platforms without generating a high overhead of multiplatform configuration and generation of JNI code. Such performance, accuracy, and ease of use are clearly highly valued.
In addition, JNA includes a platform library that has been mapped with many local functions, and a set of common interfaces that simplify local access.
Attention:
JNA is a Java class library built on the basis of JNI technology, which allows you to easily access functions in a dynamic-link library using Java directly.
Using JNI, you must manually write a dynamic-link library in C that maps the Java data types in the C language.
In JNA, it provides a dynamic C language-written forwarder that automates the data type mapping of Java and C, and you no longer need to write a C dynamic-link library.
Perhaps this also means that using JNA technology can have a slight performance penalty than invoking a dynamic-link library using JNI technology. But the overall impact is small, because JNA also avoids the overhead of some of the platform configuration of JNI.
3. JNA Simple to use
JNA's project has been migrated to GitHub, the latest version is 4.1.0, and a packaged jar file is available for download.
JNA A. dll/.so file as a Java interface, below a simple example to illustrate how to use it.
Of course, starting with the most classic HelloWorld, we call C's printf function to print out "HelloWorld" (the official example), provided the jar package is added to your classpath.
Package Com.sun.jna.examples;import Com.sun.jna.library;import Com.sun.jna.native;import com.sun.jna.Platform;/** Simple example of JNA interface mapping and usage. */public class HelloWorld { //This was the standard, stable to mapping, which supports extensive //Customizat Ion and mapping of Java to native types. Public interface Clibrary extends Library { clibrary INSTANCE = (clibrary) native.loadlibrary (( Platform.iswindows ()? "MSVCRT": "C"), clibrary.class); void printf (String format, Object ... args); } public static void Main (string[] args) { CLibrary.INSTANCE.printf ("Hello, world\n"); for (int i=0;i < args.length;i++) { CLibrary.INSTANCE.printf ("Argument%d:%s\n", I, Args[i]);}}}
Run the program, if no parameters are printed only "Hello, World", if you have parameters, will print out all the parameters.
It's easy to call a function in the external dynamic-link library directly in Java without writing a single line of C code!
Let's explain the procedure below.
(1) You need to define an interface that inherits from
Library
Or
StdCallLibrary
The default is inheritance, Library
if the function in the dynamic link library is output in stdcall, then inheritance StdCallLibrary
, such as the well-known KERNEL32 library. For example, the interface definition in the example above:
Public interface Clibrary extends Library {}
(2) Internal definition of the interface
The interface requires a common static constant: INSTANCE,
through this constant, you can obtain an instance of this interface, thereby using the interface method, which is called the external dll/so function.
This constant is obtained through the API function of Native.loadlibrary (), which has 2 parameters:
- The first parameter is the name of the dynamic-link library dll/so, but does not have a. dll or. So suffix, which is consistent with the JNI specification, because the suffix name is not allowed across the operating system platform. The order of the search dynamic link library path is: first from the current class of the current folder to find, if not found, and then find the Win32/win64 folder under the current project folder, find the corresponding DLL file search, if you can not find the next to Windows to search, and can not find will throw an exception. For example, in the example above, the printf function under the Windows Platform DLL library name is MSVCRT, and in other platforms such as Linux under the so library name is C.
- The second parameter is the class type of this interface. JNA uses this class type to dynamically create an instance of an interface based on the specified. dll/.so file. The instance is automatically generated by JNA through reflection.
Clibrary INSTANCE = (clibrary) native.loadlibrary ((Platform.iswindows ()? "MSVCRT": "C"), Clibrary.class);
The interface only needs to define the function or public variables you want to use, and what you don't need can be undefined, as the previous example only defines the printf function:
void printf (String format, Object ... args);
Note the types of parameters and return values, which should be consistent with the function types in the link library.
(3) Calling a function in a linked library
Once you have defined the interface, you can use the function in the interface, which is the function in the corresponding dll/so, and it is very simple to call the method through an instance in the interface, as in the preceding example:
CLibrary.INSTANCE.printf ("Hello, world\n"); for (int i=0;i < args.length;i++) { CLibrary.INSTANCE.printf ("Argument%d:%s\n", I, Args[i]); }
This is a simple example of the use of JNA, it may be thought that this example is too simple, because the use of the system comes with a dynamic link library, should give a self-implemented library function example. In fact, I think this is completely unnecessary, this is also the convenience of JNA, unlike JNI when using user-defined library to define a lot of configuration information, for JNA, the use of user-defined libraries and the use of the system comes with a library is exactly the same way, no need to configure what information. For example, I create a dynamic library program under Windows:
#include "stdafx.h" extern "C" _declspec (dllexport) int Add (int a, int b); int add (int a, int b) { return a + b;}
Then compile into a DLL file (such as CDLL.dll), put it in the current directory, and then write the JNA program call:
public class Dlltest {public interface Clibrary extends Library { clibrary INSTANCE = (clibrary) Native.loadlibra Ry ("Cdll", clibrary.class); int add (int a, int b); } public static void Main (string[] args) { int sum = CLibrary.INSTANCE.add (3, 6); SYSTEM.OUT.PRINTLN (sum);} }
4. JNA Technical Difficulties
Programmers who have cross-lingual, cross-platform development know that the difficulty of cross-platform and language invocation is the problem caused by inconsistent data types between different languages. The failure of most cross-platform calls is the result of this problem. In this connection, no matter what language or technical programme, this problem cannot be solved. JNA is no exception.
It is said that the functions used in the interface must be consistent with the function prototypes in the link library, which is the difficulty of JNA even all cross-platform calls, because the C + + type is different from the Java type, and you must convert the types to keep them consistent, such as the prototype of the printf function in C:
void printf (const char *format, [argument]);
You cannot write this in Java, there is no char pointer type in Java, so const char * goes to Java under String type.
This is type Mappings, and the default type mapping table given by JNA is as follows:
There are many other types of mapping, please visit the JNA official website to view.
In addition, JNA supports the 类型映射定制,比如有的Java中可能找不到对应的类型(在Windows API中可能会有很多类型,在Java中找不到其对应的类型)
ability to typemapper classes and related interfaces in JNA.
5. Can JNA completely replace JNI?
This may be a matter of concern to everyone, but unfortunately,JNA is not a complete replacement for JNI , because some needs have to be resorted to JNI.
Using JNI technology, you can not only implement Java access to C functions, but also implement C language calling Java code.
and JNA can only implement Java access C function, as a Java framework, naturally cannot implement the C language calls Java code. At this point, you still need to use JNI technology.
JNI is the foundation of JNA and the technical basis for interoperability between Java and C. Sometimes, you have to come back to basics.
6. References
(1) Jna-jni Terminator
(2) C++dll programming detailed
Reprint statement
This article was reproduced from: https://www.cnblogs.com/lanxuezaipiao/p/3635556.html
Alexia (Minmin)
If you think reading this blog gives you something to gain, you might want to click "recommend" in the lower right corner.
If you want to interact with me, welcome to micro-BO mutual powder
This article is copyright to the author and the blog Park, Welcome to reprint, but without the consent of the author must retain this paragraph, and in the article page obvious location to the original link, otherwise reserves the right to pursue legal responsibility.
Java cross-language invocation, using JNA to access the Java external interface