2016-04-26 92 views
0

首先,我發現了幾個匹配的問題,但沒有找到滿意的答案。他們大多覆蓋指針指針c參數(而不是C++)。其中一些涵蓋Python而不是Java。SWIG和Java:如何將C++指針映射到指向Java對象輸出參數的指針

我有一個C++方法,它有一個輸出參數,它是指向一個對象的指針。我想從Java調用這個方法。

在使用SWIG和Java的文檔中,我找到了this Butler example。這幾乎是我所需要的,除了它覆蓋了結構而不是對象。它也是爲C而不是C++編寫的。我從這個例子開始,認爲我需要的可能看起來很像這個例子(也許我需要一種完全不同的方法,但我仍然試了一下)。

原來的C方案是這樣的:

int HireButler(Butler **ppButler) { 
    Butler *pButler = (Butler *)malloc(sizeof(Butler)); 
    pButler->hoursAvailable = 24; 
    pButler->greeting = (char *)malloc(32); 
    strcpy(pButler->greeting, "At your service Sir"); 
    *ppButler = pButler; 
    return 1; 
} 

在我的C++版本,它看起來像這樣(我做了巴特勒類的HireButler和FireButler靜態方法):

class Butler { 
    // ... necessary class members, getters and setters go here ... 

    static int HireButler(Butler **ppButler) { 
     Butler *pButler = new Butler(); 
     pButler->setHoursAvailable(24); 
     pButler->setGreeting("At your service Sir"); 
     *ppButler = pButler; 
     return 1; 
    } 

    static void FireButler(Butler *pButler) { 
     delete pButler; 
    } 
}; 

對於SWIG interfance文件,我幾乎完全複製了示例中的代碼。除非我不得不改變C風格的JNI調用C++ - 風格JNI調用(所以這是jenv->而不是(* jenv) - >和下降的第一個參數):

// Do not generate the default proxy constructor or destructor 
%nodefaultctor Butler; 
%nodefaultdtor Butler; 

// Add in pure Java code proxy constructor 
%typemap(javacode) Butler %{ 
    /** This constructor creates the proxy which initially does not create nor own any C memory */ 
    public Butler() { 
    this(0, false); 
    } 
%} 

// Type typemaps for marshalling Butler ** 
%typemap(jni) Butler ** "jobject" 
%typemap(jtype) Butler ** "Butler" 
%typemap(jstype) Butler ** "Butler" 

// Typemaps for Butler ** as a parameter output type 
%typemap(in) Butler ** (Butler *ppButler = 0) %{ 
    $1 = &ppButler; 
%} 
%typemap(argout) Butler ** { 
    // Give Java proxy the C++ pointer (of newly created object) 
    jclass clazz = jenv->FindClass("Butler"); 
    jfieldID fid = jenv->GetFieldID(clazz, "swigCPtr", "J"); 
    jlong cPtr = 0; 
    *(Butler **)&cPtr = *$1; 
    jenv->SetLongField($input, fid, cPtr); 
} 
%typemap(javain) Butler ** "$javainput" 

後,我產生了必要的使用SWIG的Java和C++包裝代碼,一切都編譯好,Java代碼看起來不錯。然而,當我嘗試運行下面的Java代碼,我得到一個異常:

Butler jeeves = new Butler(); 
    Butler.HireButler(jeeves); 
    System.out.println("Greeting:  " + jeeves.getGreeting()); 
    System.out.println("Availability: " + jeeves.getHoursAvailable() + " hours per day"); 

從bug報告文件,異常似乎檢索使用JNI的swigCPtr場時發生:

Stack: [0x0000000002590000,0x0000000002690000], sp=0x000000000268f630, free space=1021k 
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code) 
V [jvm.dll+0x136519] 
C [TestDll.dll+0x411f] JNIEnv_::GetFieldID+0x4f 
C [TestDll.dll+0x4e05] Java_com_test_exampleJNI_Butler_1HireButler+0x95 
C 0x000000000297dcec 

不幸的是,我對JNI完全沒有經驗,所以我現在很困難。

回答

0

這是典型的,當我問我的問題後,我得到了我的時間,發現問題是什麼。

我需要在JNI調用使用完全限定類名:中

jclass clazz = jenv->FindClass("com/test/Butler"); 

代替

jclass clazz = jenv->FindClass("Butler");