如何使用 Java 本机接口将字节数组传递到以 char* 作为参数的 C 函数中



所以我需要使用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);
    }
}

这是我的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);
    }
}

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

Java char 和 C char类型不兼容,最好将byte[]传递给 C,然后根据需要转换每个元素。


大致如下:

主.java:

//...Code to load library...
public static void main(String[] args) {
    passBytes("hello".getBytes());
}
public static native void passBytes(byte[] bytes);

主:

#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);
 }

jbyteArray只不过

是一个存根类型,在 jni.h 中定义:

struct _jobject;
typedef struct _jobject *jobject;
typedef jobject jarray;
typedef jarray jbyteArray;

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

为了从中获取元素,我们将其传递给GetByteArrayElements(因为类型是byte[]),它可以要求虚拟机检索 C 样式数组中的元素。(它可能会也可能不会复制。见文档)

对数组长度执行相同的操作。

告诉 VM 我们已经完成了阵列。我们称之为ReleaseArrayElements.

此外,jbyte被定义为 signed char ,因此在这种情况下仅使用 GetByteArrayElements 的结果作为unsigend char*而不是jbyte*是安全的。

最新更新