我必须围绕现有的C源代码编写JNI包装器,以便可以从Java调用它们。但是大多数C源代码都采用命令行参数(argc和argv)并广泛使用它们。有没有什么方法可以将我在Java中捕获的字符串args []传递给C函数,对C源文件进行非常小的更改?
我相信作为JNI包装器的一部分,我必须在C语言中编写一个由Java代码调用的函数。
答案 0 :(得分:5)
当然,你必须编写一个由Java代码调用的C函数。
如Radiodef指出的答案所示,该函数将收到jobjectarray
,因为java String[]
在jni
中表示为jobjectArray
。
在函数中,你必须malloc一个C数组,用于存储遗留main
函数在它的char **argv
参数中期望的所有char *指针。
您将存储该数组malloced指针,以便能够立即释放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;
}