我必须围绕现有的 C 源代码编写 JNI 包装器,以便可以从 Java 调用它们。但是大多数 C 源代码都接受命令行参数(argc 和 argv)并广泛使用它们。有什么方法可以将我在 Java 中捕获的字符串 args[] 传递给 C 函数,而对 C 源文件的更改非常少?
我相信作为 JNI 包装器的一部分,我必须用 C 语言编写一个由 Java 代码调用的函数。
最佳答案
当然,您必须编写一个由 Java 代码调用的 C 函数。
正如在 Radiodef 指出的答案中看到的那样,该函数将接收一个 jobjectarray
,因为 java String[]
在 jni
中表示> 作为 jobjectArray
。
在该函数中,您必须 malloc 一个 C 数组,用于存储您的遗留 main
函数期望在它的 char **argv
中的所有 char* 指针争论。
您将在该数组中存储分配的指针,以便能够立即释放 JNI 对象。您可以避免那些 malloc,但代价是将 JNI 资源存储在另一个数组中以供进一步发布,所以我认为这不是一个好主意。
请记住,遗留主要功能的约定是第一个 arg(索引 0)是“程序名称”。你将不得不伪造它。
void MyJNIFunction(JNIEnv *env, jobject object, jobjectArray stringArray) {
// Get the number of args
jsize ArgCount = (*env)->GetArrayLength(env, stringArray);
// malloc the array of char* to be passed to the legacy main
char ** argv = malloc(sizeof(char*)*(ArgCount+1)); // +1 for fake program name at index 0
argv[ 0 ] = "MyProgramName";
int i;
for ( i = 0; i < ArgCount; ++i ) {
jstring string = (jstring)((*env)->GetObjectArrayElement(env, stringArray, i));
const char *cstring = (*env)->GetStringUTFChars(env, string, 0);
argv[ i + 1 ] = strdup( cstring );
(*env)->ReleaseStringUTFChars(env, string, cstring );
(*env)->DeleteLocalRef(env, string );
}
// call the legacy "main" function
LegacyMain( ArgCount + 1, argv );
// cleanup
for( i = 0; i < ArgCount; ++i ) free( argv[ i + 1 ] );
free( argv );
return;
}
关于java-native-interface - 围绕 C 主函数编写 JNI 包装器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20258134/