Using JNA, let Java invoke native code

Source: Internet
Author: User

JNA Definition:

Jna:java Native Access, a JNI-based framework developed by Sun. JNI allows Java to invoke native C or C + + code.

differences between JNA and JNI (Java Native Interface):

Performance : JNA is inferior to JNI in performance. Since JNA is a layer on the basis of JNI.
Portability: JNA is better than JNI because developers don't need to write dynamic-link libraries as proxies.
Use : JNI uses the native keyword, maps native methods using a Java method, and uses System.loadlibrary;jna to represent dynamic-link libraries using a Java pretext. Using Native.loadlibrary

JNA installation using the environment:

native code: Write native code using C + + or C, or use existing native code. Specify the extern "C" __declspec (dllexport) before preparing the function or class to be used in Java. Then package the DLL into a dynamic-link library
java code : Download Jna.jar,https://github.com/java-native-access/jna. Then put the DLL file below the detailed project.

JNA using:

1. Prepare the DLL (this part is for people who have just started learning.) Can be browsed directly to the 2nd part)
We use Java to call DLLs from the generation of DLLs to the use of JNA, step by step commentary.
The DLL is generated first. In order to learn JNA. It's best if we build the DLL ourselves, I use the dev C + + (http://sourceforge.net/projects/orwelldevcpp/) tool to write C + + code. After installing dev C + +, we create a dllproject.

Then we create an. h file and a. cpp file. We need to define inside. H:

#if BUILDING_DLL#define DLLIMPORT extern "C" __declspec(dllexport)#else#define DLLIMPORT extern "C" __declspec(dllimport)#endif

Then we define two structs and two function functions in. h:

struct UserStruct{    longid;    wchar_t* name;    int age;};DLLIMPORTvoid sayUser(UserStruct* pUserStruct);struct CompanyStruct{    longid;    wchar_t* name;    UserStruct* users[100];    int count;};DLLIMPORTvoid sayCompany(CompanyStruct* pCompanyStruct);

Note here that the function declaration needs to be DLLIMPORT, where DLLIMPORT equals extern "C" __declspec (dllexport), No special treatment is required before a struct.
Implement Sayuser and Saycompany two functions in a. cpp file:

void sayUser(UserStruct* pUserStruct){    std::wcout<<L"hello:"<<pUserStruct->name<<std::endl;}

The function of the Sayuser function is to print out the name of the USERSTRUCT structure

void sayCompany(CompanyStruct* pCompanyStruct){    std::wcout<<L"hello:"<<pCompanyStruct->name<<std::endl;    for(int i=0;i<pCompanyStruct->count;i++)    {        UserStruct* user=pCompanyStruct->users[i];        sayUser(user);    }}

The function of the Saycompany function is to print out the name of the company structure and print the name of all USERSTRUCT members at the same time.
Then we implement it in the CPP file.

BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved){    returnTRUE;}

Then build the DLL file, because the project name I defined is called jnatest, so the generated DLL file is called JNATest.dll.

2. Java calls DLL using JNA
We need to create a interface, here we name TESTDLL1, and then extends Library. We need to map the userstruct and COMPANYSTRUCT two structures to Java, such as the following code:

 Public  class userstruct extends Structure {         Public Static  class byreference extends userstruct implements Structure . byreference {}; Public Static  class byvalue extends userstruct  implements  Structure. Byvalue {} PublicNativelong ID; PublicWString name; Public intAge;}

Byreference refers to the pointer, byvalue refers to the value, then the following three fields corresponding. h file in the Userstruct three fields, the order must not be wrong. As memory is passed to the C function call, reading is read in the order of the struct in C, so the order must not be wrong.

Similarly companystruct mappings in Java are as follows:

 Public  class companystruct extends Structure{         Public Static  class byreference extends companystruct implements Structure . byreference {}; Public Static  class byvalue extends companystruct  implements  Structure. Byvalue {}; PublicNativelong ID; PublicWString name;//need to use ToArray. Because the memory space in Java is not contiguous. So use the ToArray method provided by JNA to generate contiguous memory space         PublicUserstruct.byreference[] users= (userstruct.byreference[])NewUserstruct.byreference (). ToArray ( -); Public intCount;}

There's a place that needs special attention. Otherwise, a null error occurs. is public userstruct.byreference[] users= (userstruct.byreference[]) new Userstruct.byreference (). ToArray (+); This sentence, assuming that the public userstruct.byreference[] users=new userstruct.byreference[100], then the call will be an error. The reason is that Java's memory space is usually discontinuous, and we need contiguous memory space, where we need to generate an array using the ToArray function provided by JNA.
The following piece of code is very important to load the DLL:

TestDll1 INSTANCE=(TestDll1) Native.loadLibrary("JNATest",TestDll1.class);

Then declare the native function we want to call in Java:

publicvoidsayUser(UserStruct userStruct);publicvoidsayCompany(CompanyStruct companyStruct);

Then we create a test.java, and in the main function we test whether we can invoke the native function.


First Test Sayuser:

UserStruct.ByReference userStruct=new UserStruct.ByReference();userStruct.id=new NativeLong(100);userStruct.age=30;userStruct.name=new WString("SBY");TestDll1.INSTANCE.sayUser(userStruct);

And then execute. Will print out the Hello:sby
Again test Saycompany:

Companystruct. ByreferenceCompanystruct=new companystruct. Byreference();Companystruct. ID=new Nativelong (2);Companystruct. Name=new WString ("hehe");Companystruct. Count=Ten;Userstruct. ByreferencePuserstruct=new userstruct. Byreference();Puserstruct. ID=new Nativelong ( -);Puserstruct. Age= About;Puserstruct. Name=new WString ("SBY");Puserstruct. Write();for (int i=0; i<companystruct.count;i++) {Companystruct. The Users[I]=puserstruct;}testdll1. INSTANCE. Saycompany(companystruct);

Will output a hello:hehe and 10 Hello:sby
Some places will say that the need to puserstruct.write () This line of code, the purpose is to hold the memory, not to be released by the GC, but when I test the time without adding this line can also be executed accurately. This JNA is expected to provide the ToArray function.

The above is my JNA learning experience. The reason for inserting such an article in machine learning's blog is that most of the machine Leanring's code is written in C or C + +. Some scenarios will require writing Java programs. At this point we need to use Java to invoke the C or C + + functions that have been written.
The above source Portal: Http://yun.baidu.com/share/link?

shareid=2278504517&uk=3977203577

Using JNA, let Java invoke native code

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.