Java Framework JNA calls the C method (Windows link library DLL file, Linux link library so file)

Source: Internet
Author: User

Introduction

Let's introduce a new Java framework-jna that accesses native code.

The JNA (Java Native Access) framework is an open-source Java framework that is developed by Sun and is built on the basis of classic JNI.

JNA Project Address: https://jna.dev.java.net/

very powerful, easy to use, functionally similar to. Net of P/invoke.

A terrible jni.

We know that using JNI calls. dll/.so Sharing class libraries is very, very cumbersome and painful.

If you have an existing. dll/.so file, if you use the JNI technology call, we first need to write a separate C language. dll/.so shared library, using sun-defined data structures

Instead of the C-language data structure, call the functions advertised in the existing dll/so.

Then load the adapter dll/so in Java, and then write the Java native function as the proxy for the function in the DLL.

There are 2 tedious steps 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 lackluster on the client side. It can be said that JNI is Java's

A big weakness!


. NET platform on the powerful P/invoke

And in. NET platform, the powerful P/invoke technology makes our Java programmers very envious. Using P/invoke technology, you only need to write one. NET function, plus a

declaration, you can call the functions in the DLL directly. You do not need to use the C language to write DLLs to fit.


No worse than P/invoke's JNA.

now, no need to envy. NET's p/invoke mechanism. JNA reduced the call to the Dll/.so shared library to the same level as P/invoke.

With JNA, you do not need to write an adapter. dll/.so, you only need to write an interface and some code in Java, as a proxy for the. dll/.so, you can call it in a Java program.

Dll/so.


JNA Quick Start
Now let's go straight into the JNA world.
You just need to download a jar package and you can easily invoke the C function in the dynamic-link library using the powerful features of JNA.

Import Com.sun.jna.library;import com.sun.jna.native;import com.sun.jna.platform;/** * @description: TODO * @author Somnus Date April 1, 2015 PM 1:26:56 */public class HelloWorld {public    interface Clibrary extends Library {        clibrary I Nstance = (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]);}}    
you can see that the console prints out

Hello, World

Note, however, that this program actually prints the above characters using the printf function in the C run-time library of Msvcrt.dll.

Look, how simple, no need to write a line of C code, you can directly in Java to call the external dynamic link library functions!


JNA Technology Decryption

JNA Working principle

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 automatically implements data type mappings for Java and C. You no longer need to write a C dynamic link library.

Of course, this also means that using JNA technology can have a slight performance penalty than invoking a dynamic-link library using JNI technology. The speed may be several times lower. But the impact is small.

JNA Technical Difficulties

1, the current path is under the project, not the bin output directory.

2, the corresponding relationship of data structure:

Table of JAVA-C and operating system data types

Java Type

C Type

Native representation

Boolean

Int

32-bit Integer (customizable)

Byte

Char

8-bit integer

Char

wchar_t

Platform-dependent

Short

Short

16-bit integer

Int

Int

32-bit integer

Long

Long Long, __int64

64-bit integer

Float

Float

32-bit floating Point

Double

Double

64-bit floating Point

Buffer
Pointer

Pointer

Platform-dependent (32-or 64-bit pointer to memory)

<t>[] (array of primitive type)

Pointer
Array

32-or 64-bit Pointer to memory (ARGUMENT/RETURN)
Contiguous memory (struct member)

In addition to the above types, JNA also supports mapping of common data types.

String

char*

Nul-terminated Array (native encoding or jna.encoding )

WString

wchar_t*

nul-terminated Array (Unicode)

String[]

char**

null-terminated Array of C strings

WString[]

wchar_t**

null-terminated array of wide C strings

Structure

struct*
struct

Pointer to struct (argument or return) ( or explicitly )
struct by value (member of Struct) ( or explicitly )

Union

Union

Same asStructure

Structure[]

Struct[]

Array of structs, contiguous in memory

Callback

<T> (*FP) ()

function pointer (Java or native)

NativeMapped

Varies

Depends on definition

NativeLong

Long

Platform-dependent (32-or 64-bit integer)

PointerType

Pointer

Same asPointer

JNA Programming Process
JNA a dll/.so file as a Java interface.

A DLL is a collection of C functions, a container, which is consistent with the concept of an interface.

We define such an interface,

Public interface TestDll1 extends Library {                   /**                    * The current path is under the project, not the bin output directory.                    */                   TestDll1 INSTANCE = (TestDll1) native.loadlibrary ("TestDll1", testdll1.class);                   public void Say (WString value);                   

If the DLL outputs a function in stdcall mode, it inherits Stdcalllibrary. Otherwise, the default library interface is inherited.

A common static constant is required inside the interface: instance.
TestDll1 INSTANCE = (TestDll1) native.loadlibrary ("TestDll1", Testdll1.class);
With this constant, an instance of this interface can be obtained, thereby using the method of the interface. The function that calls the external DLL!

Attention:
1. The Native.loadlibrary () function has 2 parameters:

The name of the DLL or. so file, but without the suffix name. This is consistent with the JNI specification because the suffix name is not allowed to cross the operating system platform.

The path to the search DLL is:

    • The root path of the project
    • The global path of the operating system,
    • The path specified by path.

The second parameter is the class type of this interface, and JNA dynamically creates an instance of the interface, based on the specified dll/.so file, by this class type.


2, in the interface you just need to define the function or public variables you need, and what you don't need can be undefined.

public void Say (WString value);
The type of the parameter and the return value should be the same as the type of the C function in the DLL.

This is the difficulty of JNA, and even all cross-platform calls. Here, the function parameters of the C language are: wchar_t*.

The corresponding Java type in JNA is wstirng.

In this case, I have used this type in the project, how to get the value of the output parameter in C when JNA calls C

Openssl_derivekey (    Char       * pszkey,//          output parameter, save the exported key's cache    unsigned int uilen,           //input parameter, required the length of the exported key, At this point the caller needs to guarantee the size of the cache pszkey    const char * pszinitkey,      //Input parameters: initial key    unsigned int uiinitkeylen,    //input parameter: initial key length    //   0 o'clock, when Pszinitkey is a string, automatically takes the length of the string    const char * pszsalt,         //input parameter: Salt (belongs to interference information)    unsigned int Uisaltlen,       //input parameter: the length of the salt    //   is 0 o'clock, when Pszsalt is a string, the length of the string is automatically taken    unsigned int uiiterationcount//Repeat number c18/>); 0: Success, others: Failure
The corresponding Java code

int Openssl_derivekey (string pszkey, int uilen, string pszinitkey, int uiinitkeylen, string pszsalt,            int Uisaltlen, int uiiterationcount);

How do you get the value of Pszkey when you call Java?

At this time there is a pointer class and its sub-class memory can help us, specific can see the relevant API, here I only give an example

/* Generate MAC Checksum *//************* parameter description: Input parameter:   method   : Algorithm mode 0-Hang Seng (default)                       1-standard                       2-BPI   databuf  : Mac string to be generated   datalen  : The integer length of the minimum 8 of the DATABUF string (for example, if the databuf length is 7,datalen=8.                                           If the databuf length is 13, then datalen=16)   Key      : Mac      : Generated mac   *************/char *generatemac (int method, char *databuf, int datalen, char * Key, Char *mac);

Here we need to get the value of the Mac, the Java code is as follows

public class Jnautil {public interface Nativeinterface extends Library {public static final nativeinterface in        Atance = (nativeinterface) native.loadlibrary ("Hsdes", Nativeinterface.class);         /** * Hang Seng mac algorithm:: Fill MAC_HS * @param method algorithm mode 0-Hang Seng (default) 1-Standard 2-BPI * @param databuf to generate Mac string * @param the integer length of the minimum 8 datalen databuf string (for example: if the databuf length is 7,datalen=8. If the databuf length is 13, then datalen=16) * @param key key * @param mac generated Mac * @return * NOTE:  (The method name must be the same as the C bottom, you cannot take the Hump naming method) */public String Generatemac (int method, Pointer databuf, int datalen, String key,    Pointer mac) throws Exception; /** * Generate Mac * @param method * @param databuf * @param datalen * @param key * @return * @t Hrows Exception */public static string Generatemac (int method, string databuf, int datalen, string key) throws Exc        eption{byte[] sb = Databuf.getbytes ("GB2312"); int len = Sb.leNgth;        if (len%8! = 0) {len = (LEN/8 + 1) *8;        } Pointer sp = new Memory (len);            for (int i=0;i<len;i++) {if (I < sb.length) {sp.setbyte (I, sb[i]);            }else{Sp.setbyte (i, (byte) 0x00);        }} Pointer P = new Memory (8);        NativeInterface.INATANCE.GenerateMAC (method, SP, Datalen, Key, p);        Byte[] result = P.getbytearray (0,8);    Return Stringutils.rightpad (Byte2hex (Result). toUpperCase (), 32, ' 0 ');          }//from byte array to hexadecimal string convert private static string Byte2hex (byte[] arr) {StringBuffer sb = new StringBuffer ();             for (int i = 0; i < arr.length; ++i) {final String HEX = "0123456789abcdef"; Take out the high 4 bits of this byte, and then with 0x0f and arithmetic, get a 0-15 data, through Hex.charat (0-15) that is 16 binary sb.append (Hex.charat ((Arr[i] >> 4) &am P              0x0f)); Take out the low of this byte, with 0x0f and arithmetic, get a data between 0-15, through Hex.charat (0-15) that is 16 binary number Sb.append (arr[i] & 0x0f));      } return sb.tostring (); }}


 the difficulty of all cross-platform and cross-language calls

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 regard, no matter what language, what kind of technical programme, can not solve this problem, This requires careful development and design by the programmer. This is the responsibility of the programmer.


Common cross-platform calls are:

    1. Java calls the functions in the DLL,. So dynamic link library written in the C language.
    2. NET calls the functions in the DLL,. So dynamic link library written in C by P/invoke.
    3. Through webservice, in C,c++,java,. NET, among other languages. WebService is the data that is passed in XML format.
Even powerful P/invoke or webservice can encounter a lot of difficulties in encountering complex data types and large data volumes.

because of the complex data types of a language, it is difficult to express it in another language. This is the nature of cross-platform invocation issues.

For example, WebService calls in many languages, such as Java. NET has an auto-implemented java/. NET type and XML type are mapped to a class library or tool. However, in a real-world programming environment

, these automatic conversion tools are often inadequate if the types are very complex. either object-xml mapping errors. Either map out a lot of memory.


Therefore, I personally do not quite catch a cold on these object-xml mapping frameworks. I now use WebService to extract data-building objects from XML directly using the XML processing tool. or reverse.

, manually based on the property values in object XML data.


The same is true of the invocation problem between Java and C language.

Java to invoke C-language functions, you must strictly follow the C language requirements of the amount of memory to provide Java-formatted data. The data type of the C language is perfectly modeled with the Java data type .

JNA has provided a large number of types that match the C language data type.


Cross-platform, cross-language invocation of the first principle: is to use basic, simple data types, as little as possible across the language, platform to pass data! Only you can save yourself.

If you have a complex data type and a large cross-platform data transfer in your program. Then you have to write some additional fa?ade interfaces, simplifying the type of data that needs to be passed , and passing the number

The data is simplified. Otherwise, both the difficulty of implementation and the performance of the program can be difficult to improve.


JNI still can't be wasted

we have seen the strength of JNA. How shabby the JNI is compared to it! However, there are some requirements that must be resorted to by JNI.

JNA is a framework built on the basis of JNI technology. 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. is the technical basis for Java and C interoperability.

Java Framework JNA calls the C method (Windows link library DLL file, Linux link library so file)

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.