2009-10-06 52 views
3

的SWIG文檔解釋瞭如何的各種C輸入類型,像這樣:痛飲指針和Java數組

void spam1(Foo *x);  // Pass by pointer 
void spam2(Foo &x);  // Pass by reference 
void spam3(Foo x);  // Pass by value 
void spam4(Foo x[]);  // Array of objects 

...都會採取單一類型的參數在Java中,像這樣的:

Foo f = new Foo(); // Create a Foo 
example.spam1(f); // Ok. Pointer 
example.spam2(f); // Ok. Reference 
example.spam3(f); // Ok. Value. 
example.spam4(f); // Ok. Array (1 element) 

同樣,在C返回類型:

Foo *spam5(); 
Foo &spam6(); 
Foo spam7(); 

...所有這三個功能將返回一個指向一些富對象將被分配給一個Java對象變量,最後一個需要分配一個值類型,Java垃圾回收將在發佈時處理。

但假設spam5()返回一個指向數組的指針。在Java中,我都用數組的語義來訪問單個元素,但我不認爲我可以做這個:

Foo foo[] = spam5(); 

我甚至不認爲編譯器會接受強制轉換爲(富[]),那麼這在SWIG中如何工作?

+0

我已經把我的答案,例如它。抱歉,我無法提供更多幫助。 – 2009-10-13 21:43:29

回答

4

此問題沒有簡單或自動解決方案。相信我,我看了。

問題是SWIG不知道你要返回的數組有多大,所以它不能生成Java數組。你不能將這個大小作爲參數提供給函數,(或者是總的) - typemaps不能以這種方式工作。

在一般情況下,您必須編寫另一個包裝函數,它將C數組和長度作爲out參數,並使用typemap將這兩個參數轉換爲Java數組。或者,如果您不介意使用carrays.i,則可以跳過第二步,直接使用Java直接處理C數組。

+0

太好了。我期待聽到更多。 – Buggieboy 2009-10-07 17:31:32

-1

在java中,數組是一個對象,因此,如果spam5()返回Object,那麼編譯器將允許您將它轉換爲一個Foo數組。這是有效的Java:

class Bar { 
     static class Foo {} 
     Foo[] foo = {new Foo(), new Foo()}; 
     Object o = foo; 
     // ... 
     Foo[] bar = (Foo[])o; 
    } 
+0

是的,但如果您使用SWIG綁定到返回Foo *的C函數,SWIG會認爲該函數正在返回單個Foo並生成返回Foo而不是Foo []的包裝函數。 – 2009-10-06 21:45:47

+0

我認爲大衛已經把矛頭指向了困境。 – Buggieboy 2009-10-06 21:57:13

+0

請參閱: http://stackoverflow.com/questions/1522660/java-and-sdlgetkeystate 在sdljava發生這種情況。 SWIGTYPE_p_unsigned_char返回。這是一個對象引用,我的Java編譯器似乎不想將其轉換爲數組。 – Buggieboy 2009-10-06 22:00:50

0

你總是可以直接使用JNI:

想象要檢索的xyz矢量陣列

public class demo{ 
    public native vecteur[] returnArray(); 

    .... 
} 

在痛飲包裝CXX文件中添加FUNC即會填充的java VECT陣列

JNIEXPORT jobjectArray JNICALL 
       Java_demo_returnArray 
    (JNIEnv *env, jobject jobj){ 

    jobjectArray ret; 
    int i; 
    jclass objClass; 
    jmethodID mid; 
    jobject myobj; 
    jmethodID setX; 
    objClass = env->FindClass("vect"); 
    if (!objClass) 
    { 
     printf("class not found\n"); 
     exit(0); 
    } 
    ret= (jobjectArray)env->NewObjectArray(5, // change with the size of your array or a variable 
     objClass, 
     env->NewStringUTF(""));//FIXME 
    // call javap -s myclass to know the names 
    mid=env->GetMethodID(objClass, "<init>", "()V"); // looking for the vect class constructor 
    if (!mid) 
     { 
     printf("vect() not found\n"); 
     exit(0); 
     } 


    for(i=0;i<5;i++) { 
     myobj=env->NewObject(objClass, mid); // myobj = new vect() 

     // get vect::setX method 
     setX=env->GetMethodID(objClass, "setX", "(F)V"); // looking for vect::setX method 
     if(!setX) 
      { 
      printf("method vect::setX not found\n"); 
      exit(0); 
      } 
     // call setX method with param i 
     env->CallVoidMethod(myobj, setX,(float)i); // change i with your array value 
     env->SetObjectArrayElement(
            ret,i,myobj); 
     } 
    return(ret); 
    } 

最後主類

// main.java 
public class main { 
    static { 
    System.loadLibrary("myclass"); 
    } 

    public static void main(String argv[]) { 
     demo l = new demo(); 
     vecteur f[] = l.returnArray();  
     System.out.println("array size : "+f.length); 
     for (int i = 0;i < f.length;i++) 
      System.out.println(f[i].getX()); 

    } 
}