java encapsulation, jni data return, structure transfer, etc

Posted by sk8erh4x0r on Wed, 26 Jan 2022 18:04:53 +0100

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

//