4

Java 機能を呼び出す C++ アプリがあります。私はJNIを使​​用しています。すべて正常に動作しますが、まだ小さな問題が 1 つあります。C++ アプリには、巨大な配列がいくつかあります。Java App もこのデータを必要とし、1 つの巨大な結果配列を返します。現在、データをコピーするだけです(以下のコードの平和を確認できます)。そして、これらの配列に Java アプリからポインターごとに直接アクセスする方がはるかに良いでしょう。出来ますか?私は(JVMのため)いいえだと思いますが、その場合、上司に詳しく説明する必要があります:)それで、はいまたはいいえ、そしてどのようにまたはなぜですか?

jdoubleArray in2 = env->NewDoubleArray(1000);
jdouble *elems2 = (jdouble*)calloc(1000, sizeof(jdouble));
for(int i = 0; i < 1000; i++)
{
    elems2[i] = (jdouble)inputArray[i];
}
env->SetDoubleArrayRegion(in2, 0, 1000, elems2);
if(midCD != NULL)
{
    jdouble res1 = env->CallStaticDoubleMethod(cls, midCD, in2);
    double res1c = res1;
    printf("C++.Res1: %f\n", res1c);
}
4

2 に答える 2

3

Direct ByteBuffersは、この目的のために Java 1.4 で導入されました。Java 側の新しいクラスとともに、対応する JNI 関数がありました。ネイティブ配列を ByteBuffer (および対応する IntBuffer などのビュー) でラップし、コピーを作成せずに読み取りと書き込みを行うことができます。

于 2012-12-18T00:41:15.610 に答える
1

最善の方法は、 Get<PrimitiveType>ArrayElements ルーチンを使用することです。うまくいけば、VM はピニングをサポートします:

jdoubleArray in2 = env->NewDoubleArray(1000);
jboolean isCopy;
jdouble *elems2 = env->GetDoubleArrayElements(in2, &isCopy);
for(int i = 0; i < 1000; i++)
{
    elems2[i] = (jdouble)inputArray[i];
}
env->ReleaseDoubleArrayElements(in2, elems2, 0);
elems2 = NULL;

GetDoubleArrayElements() の呼び出しの後である場合、コピーは作成されていませisCopyん。JNI_FALSE

編集:質問を読み直した後、Archie のアイデアの実装を検討することをお勧めします。これは、Java メソッドがデータをどのように使用するかによって異なります。Java メソッドが配列全体を使用しない場合、または一度にすべてを使用しない場合は、C++ 配列の Java クラス ラッパーを作成するという Archie のソリューションが、ネイティブ アクセサーを使用して適切なソリューションになる可能性があります。ただし、Java メソッドがすべてのデータを必要とする場合は、GetDoubleArrayElements() が提供する、VM にデータを取得するための最も迅速な方法が必要な場合があります。

C++ 配列のいくつかの要素に変更を加え、Java コピーにも同じ変更を加えたい場合は、SetDoubleArrayRegion()の出番です。

EDIT2:アーチーは次のようなものを指していると思います:

public class NativeDoubleArrayProxy {

    // This is the native `inputArray' pointer.
    private long p;

    private int length;

    private NativeDoubleArrayProxy(long p, int length) {
        this.p = p;
        this.length = length;
    }

    public int length() {
        return length;
    }

    public native double getDouble(int index);

    public native void getDoubles(int startingIndex, double[] out, int outOffset, int length);
}

正確な詳細は、あなたの型によって異なりますinputArray(生の C スタイルの配列ですか、それともstd::vector<double>、何か他のものですか?)。しかし、考え方としてはNativeDoubleArrayProxy、JNI 側でオブジェクトを構築し、それにキャストされたポインタを に渡すことjlongです。getDouble() および getDoubles() の JNI 実装は、C++ から Java へのコピー コードを実装します。

もちろん、ポインターが有効なままであることを確認するには、細心の注意を払う必要があります。

参照: Java オブジェクト内にネイティブ ポインターを格納する「正しい」方法は何ですか?

于 2012-12-17T23:43:47.920 に答える