public class testdll
{
static
{
System.loadLibrary("goodluck");
}
public native static int get();
public native static void set(int i);
public static void main(String[] args)
{
testdll test = new testdll();
test.set(10);
System.out.println(test.get());
}
}
First, I will reference an article to introduce a simple JNI call process.
Java is favored by people for its cross-platform features. Due to its cross-platform purpose, Java has little internal connection with local machines and limits its functions. One way to solve Java local operations is JNI.
Java calls local methods through JNI, while local methods are stored in the form of library files (on Windows platforms, DLL files and so files on UNIX machines ). By calling the internal method of the local library file, Java can achieve close connection with the local machine and call system-level interface methods.
A brief introduction and application are as follows:
I. What needs to be done in Java
In a Java program, you must declare the name of the called library in the class as follows:
static {
System.loadLibrary(“goodluck”);
}
Here, you do not need to write the extension name of the Library. The system determines whether the extension name is DLL or so.
You also need to make a local Declaration on the method to be called. The keyword is native. You only need to declare it, instead of implementing it in a specific way. As follows:
Public native static void set (int I );
Public native static int get ();
Then compile the Java program file, generate the class, and use the javah command, JNI will generate the header file of C/C ++.
For example, the content of the program testdll. Java is:
Compile it with javac testdll. Java to generate testdll. Class.
Then use javah testdll to generate the testdll. h file in the current directory. This file needs to be called by the C/C ++ program to generate the required library file.
II. C/C ++
For the generated. h header file, all C/C ++ needs to do is to implement each of its methods. Compile and connect to the database file. Copy the library file to the path of the Java program, and you can use Java to call the functions implemented by C/C ++.
Connect to the example. Let's take a look at the content of testdll. h:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include
/* Header for class testdll */
#ifndef _Included_testdll
#define _Included_testdll
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: testdll
* Method: get
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_testdll_get (JNIEnv *, jclass);
/*
* Class: testdll
* Method: set
* Signature: (I)V
*/
JNIEXPORT void JNICALL Java_testdll_set (JNIEnv *, jclass, jint);
#ifdef __cplusplus
}
#endif
#endif
In actual implementation, we only care about two function prototypes.
Jniexport jint jnicall java_testdll_get (jnienv *, jclass); and
Jniexport void jnicall java_testdll_set (jnienv *, jclass, jint );
Here, both jniexport and jnicall are JNI keywords, indicating that this function is called by JNI. Jint is a type of communication between the Java int type and the local int type through JNI. We can ignore it and use it as an int. The function name is composed of Java _, the package path of the Java program, and the function name. Parameters, we only need to care about the parameters that exist in the Java program. As for jnienv * And jclass, we generally do not need to touch it.
Well, we will use the testdll. cpp file to implement these two functions:
#include "testdll.h"
int i = 0;
JNIEXPORT jint JNICALL Java_testdll_get (JNIEnv *, jclass)
{
return i;
}
JNIEXPORT void JNICALL Java_testdll_set (JNIEnv *, jclass, jint j)
{
i = j;
}
Compile and connect to the library file. In this example, it is done in windows and the DLL file is generated. And the name must be the same as that to be called in Java. Here is Goodluck. dll. Copy Goodluck. DLL to the directory testdll. Class, and run Java testdll to check the result.
My project is complicated and I need to call the dynamic link library. In this way, when JNI transfers parameters to the C program, the parameters need to be processed and converted. Can be recognized by the C program.
The general procedure is as follows:
public class SendSMS {
static
{
System.out.println(System.getProperty("java.library.path"));
System.loadLibrary("sms");
}
public native static int SmsInit();
public native static int SmsSend(byte[] mobileNo, byte[] smContent);
}
Note that the path must contain the path of the class library. Otherwise, an exception will be thrown during the program running:
Java. Lang. unsatisfiedlinkerror: no SMS in Java. Library. Path
At java. Lang. classloader. loadlibrary (classloader. Java: 1491)
At java. Lang. runtime. loadlibrary0 (runtime. Java: 788)
At java. Lang. system. loadlibrary (system. Java: 834)
At com. mobilesoft. SMS. mobilesoftinfo. sendsms. (sendsms. Java: 14)
At com. mobilesoft. SMS. mobilesoftinfo. Test. Main (test. Java: 18)
Exception in thread "Main"
The Guidance path should be at the upper level of the. dll file. If it is indicated by. dll, it will report:
Java. Lang. unsatisfiedlinkerror: C: \ SMS. dll: Can't Find dependent Libraries
At java. Lang. classloader $ nativelibrary. Load (native method)
At java. Lang. classloader. loadlibrary0 (classloader. Java: 1560)
At java. Lang. classloader. loadlibrary (classloader. Java: 1485)
At java. Lang. runtime. loadlibrary0 (runtime. Java: 788)
At java. Lang. system. loadlibrary (system. Java: 834)
At com. mobilesoft. SMS. mobilesoftinfo. sendsms. (sendsms. Java: 14)
At com. mobilesoft. SMS. mobilesoftinfo. Test. Main (test. Java: 18)
Exception in thread "Main"
Compile and generate the header file com_mobilesoft_sms_mobilesoftinfo_sendsms.h. (It is recommended to use JBuilder for compilation. The operation is relatively simple !) This header file is the bond between Java and C. Pay special attention to the jbytearray parameter passed in the method, which will be highlighted in the following process.
/* Do not edit this file-it is machine generated */
# Include
/* Header for class com_mobilesoft_sms_mobilesoftinfo_sendsms */
# Ifndef _ included_com_mobilesoft_sms_mobilesoftinfo_sendsms
# DEFINE _ included_com_mobilesoft_sms_mobilesoftinfo_sendsms
# Ifdef _ cplusplus
Extern "C "{
# Endif
/*
* Class: com_mobilesoft_sms_mobilesoftinfo_sendsms
* Method: smsinit
* Signature: () I
*/
Jniexport jint jnicall java_com_mobilesoft_sms_mobilesoftinfo_sendsms_smsinit
(Jnienv *, jclass );
/*
* Class: com_mobilesoft_sms_mobilesoftinfo_sendsms
* Method: smssend
* Signature: ([B [B) I
*/
Jniexport jint jnicall java_com_mobilesoft_sms_mobilesoftinfo_sendsms_smssend
(Jnienv *, jclass, jbytearray, jbytearray );
# Ifdef _ cplusplus
}
# Endif
# Endif
For the dynamic link library of the C program that I want to call, the C program also needs to provide a header file, SMS. h. The methods to be called in this file are listed.
/*
* SMS API
* Author: yippit
* Date: 2004.6.8
*/
# Ifndef mcs_sms_h
# Define mcs_sms_h
# Define dllexport _ declspec (dllexport)
/* SMS storage */
# Define sms_sim 0
# Define sms_mt 1
/* SMS States */
# Define sms_unread 0
# Define sms_read 1
/* SMS type */
# Define sms_noparse-1
# Define sms_normal 0
# Define sms_flash 1
# Define sms_mmsnoti 2
Typedef struct tagsmsentry {
Int index;/* index, start from 1 */
Int status;/* read, unread */
Int type;/*-1-can't parser 0-normal, 1-flash, 2-mms */
Int storage;/* sms_sim, sms_mt */
Char date [24];
Char number [32];
Char text [144];
} Smsentry;
Dllexport int smsinit (void );
Dllexport int smssend (char * phonenum, char * content );
Dllexport int smssetsca (char * SCA );
Dllexport int smsgetsca (char * SCA );
Dllexport int smssetind (int ind );
Dllexport int smsgetind (void );
Dllexport int smsgetinfo (INT storage, int * max, int * used );
Dllexport int smssaveflash (INT flag );
Dllexport int smsread (smsentry * entry, int storage, int index );
Dllexport int smsdelete (INT storage, int index );
Dllexport int smsmodifystatus (INT storage, int index);/* unread-> Read */
# Endif
With these two header files, you can write C Programs. That is, two methods to call JNI. In the materials on the Internet, the calling methods are simple (mostly print strings), so the most troublesome part of JNI is avoided and the most critical part, parameter transfer. Because Java and C are encoded differently, the passed parameters must be processed. Otherwise, the C program will warn the parameters during compilation, for example, warning c4024: 'smssend': Different Types for formal and actual parameter 2.
The SMS. C program is as follows:
# Include "SMS. H"
# Include "com_mobilesoft_sms_mobilesoftinfo_sendsms.h"
Jniexport jint jnicall java_com_mobilesoft_sms_mobilesoftinfo_sendsms_smsinit (jnienv * ENV, jclass jobject)
{
Return smsinit ();
}
Jniexport jint jnicall java_com_mobilesoft_sms_mobilesoftinfo_sendsms_smssend (jnienv * ENV, jclass jobject, jbytearray inclueno, jbytearray smscontent)
{
Char * psmscontent;
// Jsize thearraylengthj = (* env)-> getarraylength (ENV, inclueno );
Jbyte * arraybody = (* env)-> getbytearrayelements (ENV, inclueno, 0 );
Char * pmobileno = (char *) arraybody;
Printf ("[% s] \ n", pmobileno );
// Jsize size = (* env)-> getarraylength (ENV, smscontent );
Arraybody = (* env)-> getbytearrayelements (ENV, smscontent, 0 );
Psmscontent = (char *) arraybody;
Printf ("