In the near future, we need c and java to interact with each other. We use jni technology, and there are many online tutorials. Here I refer to some cases to summarize, so as to help later people avoid detours
win
1 directly use vs to create a dll project, and run the relevant code, and JNI will not be found H. It's better to include the directory in the vc directory of the project attribute interface and add the java include (it's OK for win like this)
Another problem is the precompiled header problem. (the precompiled header is not used here, because the code still runs in linux.)
2. If you switch between debug and release during compilation, you may need to fill in the above information again. On the other hand, the dll library generated by debug may not be used by computers without vc environment. Therefore, when publishing win, you need to use the dll library generated by release
3. For dynamic library compilation, it is recommended to use java to generate header files as follows
For use before java10, {javac sendsms Java generation The class file is generated by javach SendSMS h file
Javac - H is used after java10 SendSMS. java
class SendSMS { public native int SmsInit(); public native int SmsSend(byte[] mobileNo, byte[] smContent); public native int foo(Foo fooObj); public native int SmsRead(int x,int y,double[] cText); }
Automatically generated H file is as follows: sendsms h
/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class SendSMS */ #ifndef _Included_SendSMS #define _Included_SendSMS #ifdef __cplusplus extern "C" { #endif /* * Class: SendSMS * Method: SmsInit * Signature: ()I */ JNIEXPORT jint JNICALL Java_SendSMS_SmsInit (JNIEnv *, jobject); /* * Class: SendSMS * Method: SmsSend * Signature: ([B[B)I */ JNIEXPORT jint JNICALL Java_SendSMS_SmsSend (JNIEnv *, jobject, jbyteArray, jbyteArray); /* * Class: SendSMS * Method: foo * Signature: (LFoo;)I */ JNIEXPORT jint JNICALL Java_SendSMS_foo (JNIEnv *, jobject, jobject); /* * Class: SendSMS * Method: SmsRead * Signature: (II[D)I */ JNIEXPORT jint JNICALL Java_SendSMS_SmsRead (JNIEnv *, jobject, jint, jint, jdoubleArray); #ifdef __cplusplus } #endif #endif
This will be generated later The function of h development response is as follows: send SMS c
#include <jni.h> typedef struct chuanStruts { int y; double doubletext[40]; } smsstruts; typedef struct Foo { int len; char name[100]; } Foo_t; JNIEXPORT jint JNICALL Java_SendSMS_SmsInit(JNIEnv *ev, jobject obj) { return SmsInit(); //call sms.c Inside SmsInit method } JNIEXPORT jint JNICALL Java_SendSMS_SmsSend(JNIEnv *ev, jobject obj, jbyteArray mobileno, jbyteArray smscontent) { char * psmscontent ; //jsize thearraylengthj = (*env)->getarraylength(env,mobileno); jbyte * arraybody = (*ev)->GetByteArrayElements(ev,mobileno,0); char * pmobileno = (char *)arraybody; printf("[%s]/n ", pmobileno); //jsize size = (*env)->getarraylength(env,smscontent); arraybody = (*ev)->GetByteArrayElements(ev,smscontent,0); psmscontent = (char *)arraybody; return SmsSend(pmobileno,psmscontent); //call sms.c Inside SmsSend method } JNIEXPORT jint JNICALL Java_SendSMS_SmsRead (JNIEnv *ev, jobject obj, jint x,jint y, jdoubleArray doubletext) { smsstruts example; //Self built example Structure variable double * psmscontent ; int i; jdouble * arraybody = (*ev)->GetDoubleArrayElements(ev,doubletext,0); psmscontent = (double *)arraybody; printf("%f",*psmscontent); printf("%f",*(psmscontent+1)); example.y= y; for (i=0;i<2;i++) { example.doubletext[i] = *(psmscontent+i); } return SmsRead(x,&example); //call sms.c Inside SmsRead method } JNIEXPORT jint JNICALL Java_SendSMS_foo(JNIEnv* env, jobject obj, jobject fooObj) { //printf("debug -10\n"); char buf[1024]; printf("debug -9\n"); memset(buf, 0x00, 1024); printf("debug -8\n"); Foo_t* bar = (Foo_t*)buf;//malloc(sizeof(Foo_t)); printf("debug -7\n"); jclass clazz; printf("debug -6\n"); jfieldID fid; printf("debug -5\n"); //init the bar data of C char* t = "Yachun Miao"; printf("Java_SendSMS_foo: %s %d\n", t, strlen(t)); strcpy(bar->name, "Yachun Miao"); printf("debug -4\n"); bar->len = strlen(bar->name); printf("Java_SendSMS_foo: %s %d\n", bar->name, bar->len); printf("debug -3\n"); // mapping bar of C to foo clazz = (*env)->GetObjectClass(env, fooObj); printf("debug -2\n"); if (0 == clazz) { printf("debug -1\n"); printf("GetObjectClass returned 0\n"); return (-1); } printf("debug 0\n"); fid = (*env)->GetFieldID(env, clazz, "len", "I"); printf("debug 1\n"); (*env)->SetLongField(env, fooObj, fid, bar->len); printf("debug 2\n"); fid = (*env)->GetFieldID(env, clazz, "name", "Ljava/lang/String;"); printf("debug 3\n"); jstring name = (*env)->NewStringUTF(env, bar->name); printf("debug 4\n"); (*env)->SetObjectField(env, fooObj, fid, name); printf("debug 5\n"); //free(bar); return 0; }
During development, other documents are as follows: {SMS h
#ifndef _TX_SMS_H_ #define _TX_SMS_H_ #ifdef __cplusplu* extern "C" { #endif typedef struct tagSmsEntry { int index; double text[40]; } SmsEntry; int SmsInit(void); //No parameters int SmsSend(char *phonenum, char *content); //Pointer variable parameter int SmsRead(int x,SmsEntry *entry); //Structural parameters #ifdef __cplusplus } #endif #endif
sms.c
#include "sms.h" int SmsInit(void) { printf("welcome \n"); return 1; } int SmsSend(char *phonenum, char *content) { printf("liuxiao \n"); char a[100]; memset(a, 0x00, 100); memset(a, 0x31, 99); printf("%s\n",a); printf("%s %s\n",phonenum,content); return 2; } int SmsRead(int x,SmsEntry *entry) { int i; printf("mingxin\n"); printf("%d \n",x); for (i=0;i<2;i++) { printf("%f ",entry->text[i]); } return 3; }
Note that through experience summary, it is found that # malloc(sizeof(Foo_t)) cannot be used
After use, the program crashes directly, so we can only use temporary arrays. The specific reason needs to be investigated
4 when generating dynamic library, click generate - > generate solution
linux
1 when generating library files, lib must be added in front (it feels like a xx operation)
2 when installing java, do not use the installation provided by yum. The content is incomplete and there is no include header file, so you need to download it from the official website
Specific instructions are as follows
mkdir usr/local/java cd usr/local/java wget https://download.oracle.com/java/17/latest/jdk-17_linux-x64_bin.tar.gz tar -zxvf jdk-17_linux-x64_bin.tar.gz
Then modify the additional content of the configuration file
JAVA_HOME=/usr/local/java/jdk-17.0.2 PATH=$PATH:$JAVA_HOME/bin CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar export JAVA_HOME CLASSPATH PATH
Finally, select source /etc/profile
Verify java version
If not, check the current java path with which java and then rm -rf path. At this time, you should see that the version number is correct
2. When compiling, it should be noted that the capital letter i is used when introducing the external header file. This is a pit. If it is replaced with lowercase, it will report an error. It can only be capitalized, but it is too similar to lowercase L. pay attention to generation so file, you must add lib before the file. If you do not add lib, the program will not recognize it (there are a lot of words on the Internet, but few mention this point)
3. When running Java program, Java - DJava library. path=. SendSMS. java
Relevant codes are as follows
Win vs 2019 project
https://files.cnblogs.com/files/RYSBlog/JCProtocol2.zip?t=1643077628
linux
https://files.cnblogs.com/files/RYSBlog/linuxso.zip?t=1643077619
//