How can I use the native Java interface to pass a byte array to a C function that takes char * as an argument?

Therefore, I need to use JNI to call the C function from java. I was able to successfully accomplish this when transmitting in different types of data (create my own variables, header file, shared library, blah blah), but cannot make it work with an array of bytes. Here is 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); } } 

And here is my java code (I understand that after creating the header file from this, I have to replace the C function declarations with 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); } } 

I understand that the char * type is not supported in Java and why I am trying to compile an error. Maybe I need to change the type to char [] in Java? In any case, my goal is to pass the byte array in Java to my C function, iterate over the byte array and print each element.

+5
source share
1 answer

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


Something like that:

Main.java:

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

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 is nothing more than a stub type defined in jni.h :

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

In fact, it does not contain any data. It is more or less just a memory address.

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

The same is done for array length.

To tell VM, we ended up working with an array. We call ReleaseArrayElements .

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

+6
source

All Articles