4

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

... 3 つの関数はすべて、Java オブジェクト変数に割り当てられる Foo オブジェクトへのポインタを返します。最後の関数では、リリース時に Java ガベージ コレクションが処理する値型の割り当てが必要です。

しかし、spam5() が配列へのポインタを返すとします。Java では、個々の要素にアクセスするために配列セマンティクスを使用する必要がありますが、これだけでできるとは思いません。

Foo foo[] = spam5();

コンパイラが (Foo[]) へのキャストを受け入れるとは思えませんが、これは SWIG ではどのように機能するのでしょうか?

4

3 に答える 3

5

この問題には、単純または自動的な解決策はありません。私を信じてください、私は見ました。

問題は、SWIG が返される配列の大きさを認識していないため、Java 配列を生成できないことです。関数の引数としてサイズを指定することもできません(それはひどいことです)-タイプマップはそのようには機能しません。

一般的なケースでは、C 配列と長さを出力パラメーターとして受け取る別のラッパー関数を作成し、typemap を使用してこれら 2 つのパラメーターを Java 配列に変換する必要があります。または、carrays.i を使用してもかまわない場合は、2 番目のステップをスキップして、Java から直接 C 配列を操作することができます。

于 2009-10-06T21:40:57.377 に答える
0

いつでも直接 JNI を使用できます。

xyz ベクトル配列を取得したいとします。

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

  ....
}

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

  }
}
于 2009-10-23T14:28:54.767 に答える
-1

Java では配列はオブジェクトなので、spam5()returnObjectの場合、コンパイラはそれを Foo の配列にキャストできるようにします。これは有効な Java です。

    class Bar {
        static class Foo {}
        Foo[] foo = {new Foo(), new Foo()};
        Object o = foo;
        // ...
        Foo[] bar = (Foo[])o;
    }
于 2009-10-06T21:41:40.623 に答える