代码之家  ›  专栏  ›  技术社区  ›  Buggieboy

SWIG指针和Java数组

  •  3
  • Buggieboy  · 技术社区  · 15 年前

    swig文档解释了C中的各种输入类型,如:

    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();
    

    ……所有三个函数都会返回指向某个FO对象的指针,该对象将被分配给Java对象变量,最后一个需要分配Java垃圾集合在释放后将要处理的值类型。

    但是假设spam5()返回一个指向数组的指针。在爪哇,我必须使用数组语义来访问单个元素,但我不认为我可以这样做:

    Foo foo[] = spam5();
    

    我甚至不认为编译器会接受强制转换(foo[]),那么这在swig中是如何工作的呢?

    3 回复  |  直到 15 年前
        1
  •  4
  •   David Seiler    15 年前

    这个问题没有简单或自动的解决方案。相信我,我看了看。

    问题是SWIG不知道你要返回的数组有多大,所以它不能生成一个Java数组。您不能将大小作为函数的参数提供,也不能将其作为参数提供(这样做很粗糙)-类型映射不能这样工作。

    在一般情况下,您必须编写另一个包装函数,它将C数组和长度作为OUT参数,并使用Type MeMAP将这两个参数转换成Java数组。或者,如果你不介意使用CARLIEN.I,你可以跳过第二步,直接从Java中直接使用C数组。

        2
  •  0
  •   user195301    15 年前

    您可以直接使用JNI:

    假设您想要检索一个XYZ向量数组

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

    在SWIG包CXX文件中添加将填充Java VECT数组的FUNC

    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());
    
      }
    }
    
        3
  •  -1
  •   Devon_C_Miller    15 年前

    在Java中,数组是一个对象,所以,如果 spam5() 返回 Object ,然后编译器将允许您将其强制转换为一个foo数组。这是有效的Java:

        class Bar {
            static class Foo {}
            Foo[] foo = {new Foo(), new Foo()};
            Object o = foo;
            // ...
            Foo[] bar = (Foo[])o;
        }
    
    推荐文章