ここで行ったこと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 への変換では何もする必要がないため、javain
typemap は単なるパススルーです。JNI の C++ 側ではjlongArray
、別の typemap で指定した です。
次にin
、jlongArray から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);
}
}
これはまさにあなたが望んでいたとおりでした。