如何将 void ** 从 JNI C 代码传递给 C 库?
How to pass void ** to a C library from JNI C code?
1) image_api.h 定义了以下方法 -
int process_image(const char *svgData, void **mapData);
2) 现在我需要调用此方法并将正确的值传递给从 image_api.so 文件
加载的 process_image
-- 在 JNI C 包装器代码中创建 void** 实例的正确方法是什么?
3)
JNIEXPORT jint JNICALL Java_JNITest_process_image(JNIEnv *env, jstring svgData, jobject mapData, jint status) {
const char *str;
str = (*env)->GetStringUTFChars(env, svgData, NULL);
**status = process_image(str, (void**)&mapData);**
return status;
}
////////////
我在调用 process_image 时遇到 UnsatisfiedLinkError,因为方法签名不匹配
在你的代码中
JNIEXPORT jint JNICALL
Java_JNITest_process_image(JNIEnv *env,
jstring svgData,
jobject mapData, // this is some Java object, you need to access it
// take a look here:
// http://jnicookbook.owsiak.org/recipe-No-020/
jint status // you don't need that, and you can't return value
// like this in JNI
) {
const char *str;
str = (*env)->GetStringUTFChars(env, svgData, NULL);
// Question is ... what exactly process_image does?
// without any additional knowledge about process_image
// it is hard to guess what goes here
int status = process_image(str, &pointer_to_some_memory_region );
return status;
}
根据更新,如果没有 Java,代码将如下所示:
void * mapData;
int status = process_image(svgData, &mapData);
...
int result = process_MapData(mapData);
现在我们要从单独的本机 Java 方法中调用 process_image 和 process_MapData:
processImage(svgData, ?);
...
int result = processMapData(?);
注意Java没有指针,所以我们必须想办法包装void*
。幸运的是,这种指针的大小是 64 位或更少。 Java 具有标准数据类型 long,大小正好合适。
所以,我们可以使用
native static long processImage(String svgData);
native static int porocessMapData(long mapPtr);
...
long mapPtr = processImage(svgData);
...
int result = processMapData(mapPtr);
这是C面:
JNIEXPORT jlong JNICALL Java_JNITest_processImage(JNIEnv *env, jclass clazz, jstring svgData) {
char *str = (*env)->GetStringUTFChars(env, svgData, NULL);
void* mapData;
process_image(str, &mapData);
(*env)->ReleaseStringUTFChars(env, svgData, str);
return (jlong)mapData;
}
JNIEXPORT jint JNICALL Java_JNITest_processMapData(JNIEnv *env, jlcass clazz, jlong mapData) {
return process_mapData((void *)mapData);
}
1) image_api.h 定义了以下方法 - int process_image(const char *svgData, void **mapData);
2) 现在我需要调用此方法并将正确的值传递给从 image_api.so 文件
加载的 process_image-- 在 JNI C 包装器代码中创建 void** 实例的正确方法是什么?
3)
JNIEXPORT jint JNICALL Java_JNITest_process_image(JNIEnv *env, jstring svgData, jobject mapData, jint status) {
const char *str;
str = (*env)->GetStringUTFChars(env, svgData, NULL);
**status = process_image(str, (void**)&mapData);**
return status;
}
////////////
我在调用 process_image 时遇到 UnsatisfiedLinkError,因为方法签名不匹配
在你的代码中
JNIEXPORT jint JNICALL
Java_JNITest_process_image(JNIEnv *env,
jstring svgData,
jobject mapData, // this is some Java object, you need to access it
// take a look here:
// http://jnicookbook.owsiak.org/recipe-No-020/
jint status // you don't need that, and you can't return value
// like this in JNI
) {
const char *str;
str = (*env)->GetStringUTFChars(env, svgData, NULL);
// Question is ... what exactly process_image does?
// without any additional knowledge about process_image
// it is hard to guess what goes here
int status = process_image(str, &pointer_to_some_memory_region );
return status;
}
根据更新,如果没有 Java,代码将如下所示:
void * mapData;
int status = process_image(svgData, &mapData);
...
int result = process_MapData(mapData);
现在我们要从单独的本机 Java 方法中调用 process_image 和 process_MapData:
processImage(svgData, ?);
...
int result = processMapData(?);
注意Java没有指针,所以我们必须想办法包装void*
。幸运的是,这种指针的大小是 64 位或更少。 Java 具有标准数据类型 long,大小正好合适。
所以,我们可以使用
native static long processImage(String svgData);
native static int porocessMapData(long mapPtr);
...
long mapPtr = processImage(svgData);
...
int result = processMapData(mapPtr);
这是C面:
JNIEXPORT jlong JNICALL Java_JNITest_processImage(JNIEnv *env, jclass clazz, jstring svgData) {
char *str = (*env)->GetStringUTFChars(env, svgData, NULL);
void* mapData;
process_image(str, &mapData);
(*env)->ReleaseStringUTFChars(env, svgData, str);
return (jlong)mapData;
}
JNIEXPORT jint JNICALL Java_JNITest_processMapData(JNIEnv *env, jlcass clazz, jlong mapData) {
return process_mapData((void *)mapData);
}