在C main函数周围编写JNI包装器

时间:2013-11-28 05:06:07

标签: java-native-interface

我必须围绕现有的C源代码编写JNI包装器,以便可以从Java调用它们。但是大多数C源代码都采用命令行参数(argc和argv)并广泛使用它们。有没有什么方法可以将我在Java中捕获的字符串args []传递给C函数,对C源文件进行非常小的更改?

我相信作为JNI包装器的一部分,我必须在C语言中编写一个由Java代码调用的函数。

1 个答案:

答案 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;
}