Java calls C + + dynamic-link library using JNI
Use JNI to connect DLL dynamic-link libraries and invoke functions in them
First C + + write good correlation function, file name is test.cpp, use g++ compile as DLL file, instruction is as follows:
g++-shared-wl,--kill-at,--output-def,test.def-o test.dll test. CPP
This creates both the Test.def and Test.dll files at the same time as the path.
By the way,. lib files can be generated with a. def file, and the build method is in VS
Lib/def:xxx.def/machine:x86 (or X64) command
After getting the. dll file, Java can theoretically use JNI to invoke the
Public classJNIDemo1 { Public Static native Shortconnectcnc (String IP); Public Static native voidWriteData (); Static{system.loadlibrary ("Melwin"); System.loadlibrary ("Melcfg"); System.loadlibrary ("Melsmem"); System.loadlibrary ("Chgapivl"); System.loadlibrary ("Meldev"); System.loadlibrary ("Melmdldr"); System.loadlibrary ("MELVNCKD"); System.loadlibrary ("Ncmocha"); System.loadlibrary ("Nccom"); System.loadlibrary ("NCAPI32"); System.loadlibrary ("Test"); }//The system will determine its own suffix. Public Static voidMain (string[] args) { ShortRES=CONNECTCNC ("192.168.200.1"); if(res==0) {System.out.println ("Connect success!\tdata writing...\n"); WriteData (); }Else{System.out.println ("Connect Fail.code:" +res); } }}
Two native function is a C + + function to invoke
You need to use the native keyword in the main class to define it beforehand
Load lib file suffix do not describe, let Java according to the OS platform to judge itself
The command to load Lib has a sequential order, so be sure to write the order of command in the call hierarchy.
If you do not know the order of calls between DLLs, you can download the DLL dependent view tool to parse the DLL
Error when loading DLL no test in Java.library.path
The reason is that JNI cannot find where your DLL file is, so adjust the Eclipse Project project's Build Path
Modify the native library location in the JDK to point to your DLL path, as follows:
If the g++ of the compiled DLL is 64-bit and the JDK is 32-bit, an error will be
Can ' t load AMD 64-bit. dll on a IA 32-bit platform
The reverse will be error
Can ' t load IA 32-bit. dll on a AMD 64-bit platform
In this case, there is no need to attempt to replace the g++ compiler because the external DLLs that are referenced are mostly 32-bit
And our JDK can install both 32-bit and 64-bit, which does not conflict in the system
So you should go to download the corresponding schema to recompile the Java file to execute the JDK
After compiling the Java file, do not rush to run, and some work to go back to C + + to complete
Compile to get the. class file, General Eclipse save a good. class file with no syntax errors
cmd to the SRC root directory, use the Javah command to generate the. h header file, or you can write the. h header directly, in the following format:
/*Do not EDIT this file-it are machine generated*/#include<jni.h>/*Header for Class Com_saiyang_newflypig_jnidemo_jnidemo1*/#ifndef _included_com_saiyang_newflypig_jnidemo_jnidemo1#define_included_com_saiyang_newflypig_jnidemo_jnidemo1#ifdef __cplusplusextern "C" {#endif/** CLASS:COM_SAIYANG_NEWFLYPIG_JNIDEMO_JNIDEMO1 * METHOD:CONNECTCNC * Signature: (ljava/lang/string;) S*/jniexport jshort jnicall java_com_saiyang_newflypig_jnidemo_jnidemo1_connectcnc (JNIEnv*, Jclass, jstring); Jniexportvoidjnicall java_com_saiyang_newflypig_jnidemo_jnidemo1_writedata (jnienv*, Jclass); #ifdef __cplusplus}#endif#endif
Function name don't be mistaken, JNI is going to look for the relevant function through these specifications.
You can call the functions of any other pure format that you write directly in the canonical function
The. h header file has a natural need to modify the CPP file:
#defineBuild_mit_dll#include<stdio.h>#include<string>#include"melncapi.h"#include"ncmcapi.h"#include"melsect.h"#include"melssect.h"#include"meltype.h"#include"test.h" using namespacestd;voidReadData ();voidWriteData (); ShortCONNECTCNC (string);Char* Jstring2char (jnienv*, jstring); intMain () {DWORD res=CONNECTCNC ("192.168.200.1"); if(Res! =0) {printf ("fail...code:%d\n", RES); } Else{printf ("Connect success!\n"); WriteData (); } return 0;} ShortCONNECTCNC (stringIP) {Meldevicedata melioctldata; DWORD dwstatus=0; MelIoctlData.uniDeviceInfo.Tcp.lPortNo=683; memset (MELIOCTLDATA.UNIDEVICEINFO.TCP.IPADDR,0, -); strcpy (MelIoctlData.uniDeviceInfo.Tcp.IPAddr, Ip.data ()); Melioctldata.dwdevicetype=devicetype_tcp; //long oldtimeout = 0, TimeOut = 2; //dwstatus = Melioctl (NULL, Adr_machine (1), dev_get_commtimeout, &oldtimeout); //if (dwstatus = = 0)//Melioctl (NULL, Adr_machine (1), dev_set_commtimeout, &timeout);Dwstatus = Melioctl (NULL, Adr_machine (1), Dev_set_commaddress, &melioctldata); returnDwstatus;} voidReadData () {//long lsectionnum = M_sec_plc_dev_word; //m_sec_plc_dev_bit, M_sec_plc_dev_char, M_sec_plc_dev_word LongLsectionnum =M_sec_plc_dev_bit; LongLaddress = Adr_machine (1); LongLaxisflag =0; ShortLgetdata =0; Shorty=0; while(SCANF ("%d", &y), y!=-1){ LongLsubsectionnum =M_ssec_pllng_y_1shot (Y); DWORD dwstatus= Melgetdata (NULL, laddress, Lsectionnum, Lsubsectionnum, Laxisflag, &Lgetdata, T_long); printf ("%d\n", Lgetdata); }} voidWriteData () {LongLsectionnum =M_sec_plc_dev_bit; LongLaddress = Adr_machine (1); LongLaxisflag =0; ShortLsetdata; ShortXnum; while(SCANF ("%d", &xnum), xnum!=-1) {scanf ("%d",&lsetdata); LongLsubsectionnum =M_ssec_pllng_x_1shot (Xnum); DWORD dwstatus= Melsetdata (NULL, laddress, Lsectionnum, Lsubsectionnum, Laxisflag, &Lsetdata, T_long); if(Dwstatus = =0) {printf ("Write success!\n"); }Else{printf ("Write fail!code:%d\n", dwstatus); }}} Jniexport jshort jnicall java_com_saiyang_newflypig_jnidemo_jnidemo1_connectcnc (JNIEnv*env, Jclass, jstring IP) { returnCONNECTCNC (Jstring2char (ENV,IP));} JniexportvoidJnicall Java_com_saiyang_newflypig_jnidemo_jnidemo1_writedata (JNIENV *, Jclass) {WriteData ();} /** * Return value char* This represents the first address of the char array * JSTRING2CSTR converts the type of jstring in Java into a char string in the C language*///jstring to char*Char* Jstring2char (jnienv*env, jstring jstr) { Char* Rtn =NULL; Jclass clsstring= Env->findclass ("java/lang/string"); Jstring Strencode= Env->newstringutf ("Utf-8"); Jmethodid Mid= Env->getmethodid (clsstring,"getBytes","(ljava/lang/string;) [B"); Jbytearray Barr= (Jbytearray) env->Callobjectmethod (Jstr, Mid, Strencode); Jsize Alen= env->Getarraylength (Barr); Jbyte* ba = env->getbytearrayelements (Barr, Jni_false); if(Alen >0) {Rtn= (Char*)malloc(Alen +1); memcpy (RTN, BA, Alen); Rtn[alen]=0; } env->releasebytearrayelements (Barr, BA,0); returnRtn;}
That's it, remember that we started the g++ command to compile the DLL?
Once again, after generating the. dll, execute the Java program and you should be able to invoke it.
Java calls C + + dynamic-link library using JNI