2013-11-28 80 views
1

我必須圍繞現有的C源代碼編寫JNI包裝,以便可以從Java調用它們。但是大多數C源代碼都使用命令行參數(argc和argv)並廣泛使用它們。有沒有什麼方法可以將我在Java中捕獲的字符串args []傳遞給C函數,並對C源文件進行非常小的更改?圍繞C主函數編寫JNI封裝

我相信作爲JNI包裝的一部分,我必須在C編寫一個由Java代碼調用的函數。

+0

[傳遞字符串數組從Java到C與JNI]的可能重複(http://stackoverflow.com/questions/5972207/passing-string-array-from-java-to-c-with-jni ) – Radiodef

回答

4

當然,您必須編寫由Java代碼調用的C函數。

如在Radiodef指出的答案中看到的那樣,該函數將收到jobjectarray,因爲jni中的java String[]表示爲jobjectArray

在該函數中,您將不得不malloc一個C數組,用於存儲您的傳統main函數所期望的所有char *指針的參數char **argv

您將在該數組中存儲malloced指針,以便能夠立即釋放JNI對象。你可能會避免使用malloc,但是需要將JNI資源存儲到另一個數組中以供進一步發佈,所以我認爲這不是一個好主意。

請記住,傳統主要函數的約定是第一個參數(索引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; 
} 
+0

使用'GetStringUTFChars'假定LegacyMain函數可以採用Java Unicode字符串的_modified_ UTF-8編碼。最好知道它所期望的編碼和字符集,並使用'String.getBytes(...)'在Java中轉換爲它。 –

+0

@TomBlodget你是對的。不知道我是否必須更新。我的代碼在普通的舊式ASCII 7位參數中工作得很好嗎? – manuell

+0

它看起來會,但我想不出任何使用完整的ASCII和只有ASCII的系統。程序參數通常是文件系統路徑。我想不出任何使用ASCII的文件系統。 –