如何使用Java本地接口为一个字节数组传递到一个C函数,它接受一个char *作为参数? [英] How can I use Java Native Interface to pass a byte array into a C function which takes a char* as an argument?

查看:196
本文介绍了如何使用Java本地接口为一个字节数组传递到一个C函数,它接受一个char *作为参数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以,我需要使用JNI从Java调用C函数。我已经能够传递不同的数据类型(创建本地变量,头文件,共享库,等等等等)时,成功地做到这一点,但不能让它使用一个字节数组工作。这里是我的C函数:

So I need to use JNI to call a C function from java. I've been able to successfully do this when passing in different data types (create the native variables, header file, shared library, blah blah), but can't get it to work with a byte array. Here's my C function:

#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 code(我的理解,从这个制作一个头文件之后,我有在头文件的JNI code来代替C函数的声明)

And here's my java code (I understand that after making a header file from this, I have to replace the C function declarations by the JNI code in the header file)

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

我得到了的char *类型不支持Java,这就是为什么我得到想要编译错误。也许我应该改变成char []在Java中的类型?不管怎么说,我的目标是能够在Java字节数组传递到我的C函数,通过字节数组迭代,并打印出每个元素。

I get that the char* type isn't supported in Java and that's why I'm getting an error trying to compile. Perhaps I should change the type to char[] in Java? Anyways, my goal is to be able to pass a byte array in Java into my C function, iterate through the byte array, and print out each element.

推荐答案

在Java 字符和C 字符类型不兼容,它可能会更好地传递字节[] 到C,然后再转换需求的每个元素。

The Java char and C char types are incompatible, it would probably be better to pass the byte[] to C and then convert each element on demand.

沿着这些路线的内容:

Main.java

Main.java:

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

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

public static native void passBytes(byte[] bytes);

MAIN.C:

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


jbyteArray 无非是那么存根类型,在 jni.h 定义的:


jbyteArray is nothing more then a stub type, defined in jni.h:

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

实际上它并不包含任何数据。它或多或少是只是一个存储器ADRESS

It doesn't actually contain any data. It is more or less just a memory adress.

要得到它的元素,我们把它传递给的 GetByteArrayElements (因为类型是字节[] ),它可以多问虚拟机检索在C风格的数组中的元素。 (这可能会或可能不会进行复印。见DOC)

To get the elements from it we pass it to GetByteArrayElements (since the type was byte[]) which can than ask the VM to retrieve the elements in a C style array. (It might or might not make a copy. See doc)

同样是为数组的长度进行。

The same is done for the array length.

要告诉VM我们与数组完成。我们呼吁 ReleaseArrayElements

To tell the VM we're done with the array. We call ReleaseArrayElements.

此外, jbyte 定义为符号字符,所以只是用的结果GetByteArrayElements unsigend的char * 而不是 jbyte * 在这种情况下是安全的。

Also, jbyte is defined as signed char, so just using the result of GetByteArrayElements as an unsigend char* instead of jbyte* is safe in this case.

这篇关于如何使用Java本地接口为一个字节数组传递到一个C函数,它接受一个char *作为参数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆