如何使用Java Native Interface将字节数组传递给C函数,该函数将char*作为参数?

6 c java java-native-interface buffer char

所以我需要使用JNI从java调用C函数.在传递不同的数据类型(创建本机变量,头文件,共享库,等等)时,我已经能够成功地执行此操作,但无法使其与字节数组一起使用.这是我的C函数:

#include <stdio.h>
void encrypt(int size, unsigned char *buffer);
void decrypt(int size, unsigned char *buffer);

void encrypt(int size, unsigned char *buffer){
    for(int i=0; i<size; i++){
        unsigned char c = buffer[i];
        printf("%c",c);
    }
}
void decrypt(int size, unsigned char *buffer){
    for(int i=0; i<size; i++){
        unsigned char c = buffer[i];
        printf("%c",c);
    }
}
Run Code Online (Sandbox Code Playgroud)

这是我的java代码(据我所知,在从此创建头文件之后,我必须用头文件中的JNI代码替换C函数声明)

class Tester{
    public native void encrypt(int size, char *buffer);
    public native void decrypt(int size, char *buffer);
    static{
    System.loadLibrary("buffer");
    {
    public static void main(String[] args){
        Tester test = new Tester();
        String hello = "hello";
        byte[] byteHello = hello.getBytes();
        test.encrypt(5,byteHello);
        test.decrypt(5,byteHello);
    }
}
Run Code Online (Sandbox Code Playgroud)

我得到Java中不支持char*类型,这就是我尝试编译时出错的原因.也许我应该在Java中将类型更改为char []?无论如何,我的目标是能够将Java中的字节数组传递给我的C函数,遍历字节数组,并打印出每个元素.

Jor*_*nee 7

Java char和C char类型是不兼容的,传递byte[]给C然后根据需要转换每个元素可能会更好.


这些方面的东西:

Main.java:

//...Code to load library...

public static void main(String[] args) {
    passBytes("hello".getBytes());
}

public static native void passBytes(byte[] bytes);
Run Code Online (Sandbox Code Playgroud)

MAIN.C:

#include "Main.h" // Main.h is generated

JNIEXPORT void JNICALL Java_Main_passBytes
  (JNIEnv *env, jclass clazz, jbyteArray array) {
    unsigned char* buffer = (*env)->GetByteArrayElements(env, array, NULL);
    jsize size = (*env)->GetArrayLength(env, array);

    for(int i = 0; i < size; i++) {
        printf("%c", buffer[i]);
    }

    (*env)->ReleaseByteArrayElements(env, array, buffer, JNI_ABORT);
 }
Run Code Online (Sandbox Code Playgroud)

jbyteArray只不过是一个存根类型,定义jni.h如下:

struct _jobject;
typedef struct _jobject *jobject;
typedef jobject jarray;
typedef jarray jbyteArray;
Run Code Online (Sandbox Code Playgroud)

它实际上不包含任何数据.它或多或少只是一个记忆地址.

为了从中获取元素,我们将它传递给GetByteArrayElements(因为类型是byte[]),这可以要求VM检索C样式数组中的元素.(它可能会也可能不会复制.请参阅doc)

对阵列长度也是如此.

告诉VM我们已经完成了数组.我们打电话ReleaseArrayElements.

此外,jbyte被定义为signed char,所以只是使用的结果GetByteArrayElementsunsigend char*,而不是jbyte*在这种情况下是安全的.