围绕C main函数编写JNI包装器

Adi*_*tya 2 java-native-interface

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

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

man*_*ell 6

当然,您必须编写一个Java代码调用的C函数。

正如指向Radiodef答案看出,函数将收到一个jobjectarray,作为一个Java String[]在表示jnijobjectArray

在该函数中,您将必须分配一个C数组,用于main在其char **argv参数中存储您的传统函数期望的所有char *指针。

您将在该数组中存储malloc指针,以便能够立即释放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;
}
Run Code Online (Sandbox Code Playgroud)