Aditya
Aditya

Reputation: 103

writing a JNI wrapper around a C main function

I have to write JNI wrappers around existing C source codes so that they can be called from Java. But most of the C source codes take in command line arguments (argc and argv) and use them extensively. Is there any way that I can pass the string args[] that I capture in Java, to the C function with very minimal changes to the C source file?

I believe that as part of the JNI wrappers, I have to write a function in C that is called by the Java code.

Upvotes: 2

Views: 1304

Answers (1)

manuell
manuell

Reputation: 7620

For sure, you'll have to write a C function called by the Java code.

As seen in the answer pointed to by Radiodef, that function will receive a jobjectarray, as a java String[] is represented in jni as a jobjectArray.

In the function, you will have to malloc a C arrays, for storing all the char* pointers that your legacy main function is expecting in it's char **argv argument.

You will store in that array malloced pointers, in order to be able to release the JNI objects immediately. You may avoid those malloc, but at the cost of storing JNI resources in another array for further release, so I don't think it's a goo idea.

Remember that the convention for legacy main functions is that the first arg (index 0) is the 'program name'. You will have to fake it.

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

Upvotes: 6

Related Questions