5

以下のようなサンプル .h ファイルがあります。

class Test
{
public:
       void SelectValues(long long values[])
};

SWIG を使用し、以下の .i ファイルから JNI インターフェイスを作成しました

%module MyLib
%include "carrays.i"
%array_functions(long long, long_long_array )


%{
  #include "Test.h"
%}

/* Let's just grab the original header file here */
%include <windows.i> /*This line is used for calling conventions*/ 
% include "Test.h"

Java メソッドを作成すると、次のように作成されます。

public void SelectValues(SWIGTYPE_p_long_long includeKeys)

また、JNIファイルの場合は引数を取りますjlongArrayが、単純なjlongものしか取りません。この問題により、long like の配列を作成しlong[]={1L,2L}、それを上記の Java メソッドに渡して適切な JNI メソッドを呼び出すことができません。

上記の配列を C++ メソッドに渡すことができるように、SWIG がインターフェイスを生成するようにします。

この質問を読みましたが、Java から C++ に配列を渡す方法を理解するのに役立ちませんでした。

4

1 に答える 1

2

ここで行ったことarray_functionsは正しく、使用可能ですが、C++ コードを直接ラップすることに重点が置かれており、基盤となる Java 配列は使用されません。次のようなもので使用できます。

SWIGTYPE_p_long_long array = MyLib.new_long_long_array(100); // new array with 100 elements.
for (int i = 0; i < 100; ++i) {
  long_long_array_setitem(array, i, i);
}
new Test().SelectValues(array);

ここで、array は、Java 側で読み取り/書き込みを行い、ラップされた関数に渡すことができる「実際の」C++ メモリ チャンクへの単なるプロキシです。

あなたの質問から、これをJava側でより「自然」に感じさせることに興味があると推測しています。SWIG もarray_class、配列を同様にラップしますが、静的関数のコレクションではなく適切なオブジェクトとして提供します。たとえば、インターフェイス ファイルをarray_class(long long, LongLongArray)代わりに使用するように変更した場合は、次のようにarray_functionsします。

LongLongArray array = new LongLongArray(100);
for (int i = 0; i < 100; ++i) {
   array.setitem(i,i); 
}
new Test().SelectValues(array.cast());

必要に応じて、いくつかのタイプマップを使用して、実際に SWIG にそれ以上のことをさせることができます。あなたの例のクラスは長さを取りませんSelectValuesので、いくつかの簡単な変更で長さを同様にうまく渡すことができますが、配列を終了していると仮定しています。

(便宜上%inline、ファイルの数を減らすためにクラスを作成し、テスト用にダミーの実装を追加しました)

%module MyLib

%{
#include <iostream>
%}

%typemap(jtype) long long values[] "long[]"
%typemap(jstype) long long values[] "long[]"
%typemap(javain) long long values[] "$javainput"
%typemap(jni) long long values[] "jlongArray"
%typemap(in) long long values[] {
  jboolean isCopy;
  $1 = JCALL2(GetLongArrayElements, jenv, $input, &isCopy);
}

%inline %{
class Test
{
public:
  void SelectValues(long long values[]) {
    while (*values) {
      std::cout << *values++ << "\n";
    }
  }
};
%}

ここで、SWIG が生成するプロキシ クラスとそれが生成する JNI クラスの両方がlong[]、つまり Java 配列と連携することになると述べました。Java Proxy から Java JNI への変換では何もする必要がないため、javaintypemap は単なるパススルーです。JNI の C++ 側ではjlongArray、別の typemap で指定した です。

次にin、jlong​​Array からlong long[]C++ 側への変換を手配するための型マップが必要です。そのための単一の JNI 呼び出しがあり、最終的に使用する JVM からのコピーまたは実際のメモリであるかどうかは気にしません。(たとえば、結果を変更して Java 内で表示できるようにしたい場合は気にするかもしれません)

私はこれをテストしました:

public class run {
  public static void main(String[] argv) {
    System.loadLibrary("mylib");
    long arr[] = {100,99,1,0}; // Terminate with 0!
    new Test().SelectValues(arr);
  }
}

これはまさにあなたが望んでいたとおりでした。

于 2012-06-08T13:38:21.597 に答える