将Java的双精度数组传递给Android Studio项目中的C++。

huangapple go评论88阅读模式
英文:

Pass Java double array to C++ in Android Studio project

问题

C++代码:

#include <jni.h>
#include <string>

extern "C" JNIEXPORT jstring JNICALL
Java_com_example_covid19_MainActivity_stringFromJNI(
        JNIEnv* env,
        jobject /* this */) {
    std::string hello = "Test string from C to java";
    return env->NewStringUTF(hello.c_str());
}

extern "C" JNIEXPORT jobjectArray JNICALL
Java_com_example_covid19_MainActivity_getDouble(JNIEnv *env, jobject /* this */) {
    double initialArray[] = {0, 4, 5, 6, 7};
    jsize length = sizeof(initialArray) / sizeof(initialArray[0]);

    jclass doubleClass = env->FindClass("java/lang/Double");
    jobjectArray doubleArray = env->NewObjectArray(length, doubleClass, NULL);

    for (int i = 0; i < length; i++) {
        jdouble value = initialArray[i];
        jobject doubleObject = env->NewObject(doubleClass, env->GetMethodID(doubleClass, "<init>", "(D)V"), value);
        env->SetObjectArrayElement(doubleArray, i, doubleObject);
    }

    return doubleArray;
}

Java代码:

public class MainActivity extends AppCompatActivity {

    // Used to load the 'native-lib' library on application startup.
    static {
        System.loadLibrary("native-lib");
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Example of a call to a native method
        TextView tv = findViewById(R.id.sample_text);
        tv.setText(stringFromJNI());
    }

    public double[] getDouble(){
        double[] j = {0, 4, 5, 6, 7};
        return j;
    }

    /**
     * A native method that is implemented by the 'native-lib' native library,
     * which is packaged with this application.
     */
    public native String stringFromJNI();
    
    public native double[] getDouble();
}
英文:

I'm working in an Android Studio project in Java that requires C++ for some signal processing functions. I need to be able to pass an array type Double from Java to C++. I've tried to lean heavily on examples, such as this (https://stackoverflow.com/questions/21065390/get-java-array-from-c-via-jni?noredirect=1&amp;lq=1), with the MainActivity.java file already linked as a jobject in my native-lib.cpp file, I think I am making this too complicated. Is there is an easier way to pass variables back and forth? (In my very rudimentary example below, I created a method called 'getDouble' just to test this out)

C++ code:

#include &lt;jni.h&gt;
#include &lt;string&gt;

extern &quot;C&quot; JNIEXPORT jstring JNICALL
Java_com_example_covid19_MainActivity_stringFromJNI(
        JNIEnv* env,
        jobject /* this */) {
    std::string hello = &quot;Test string from C to java&quot;;
    return env-&gt;NewStringUTF(hello.c_str());

    &quot;()[java/lang/Double;&quot; describes a method expecting no arguments and returning a double array.
            jmethodID methodID = env-&gt;GetMethodID(MainActivity, &quot;getDouble&quot;, &quot;()[java/lang/Double;&quot;);
}
jobjectarray doubles = env-&gt;CallObjectMethod(MainActivity, methodID);

int index = 0;
jdouble doubleArray = env-&gt;GetObjectArrayElement(double, index);

Java code:

public class MainActivity extends AppCompatActivity {

    // Used to load the &#39;native-lib&#39; library on application startup.
    static {
        System.loadLibrary(&quot;native-lib&quot;);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Example of a call to a native method
        TextView tv = findViewById(R.id.sample_text);
        tv.setText(stringFromJNI());
    }

    public double[] getDouble(){
        double[] j = {0, 4, 5, 6, 7};

        return j;
    }

    /**
     * A native method that is implemented by the &#39;native-lib&#39; native library,
     * which is packaged with this application.
     */
    public native String stringFromJNI();
}

答案1

得分: 1

不,你的方法基本上是正确的。然而,实现有点问题:

  • 你应该通过使用 env->GetObjectClass(obj) 来获取对 MainActivity 类的引用,其中 obj 是你的函数的第二个参数。
  • getDouble 的签名是 ()[D。使用 javap -s 来查看正确的签名,而不是猜测。

如果数组很大,你可能要考虑使用 GetDoubleArrayRegion 来获取可以直接读取的 double*,或者使用 GetDoubleArrayElements/ReleaseDoubleArrayElements 来进行操作。

英文:

No, your approach is pretty much correct. The implementation is a bit off, however:

  • You should get a reference to the MainActivity class by using env-&gt;GetObjectClass(obj), where obj is the second argument of your function.
  • The signature of getDouble is ()[D. Use javap -s to see correct signatures instead of guessing.

If the array is large you might want to consider GetDoubleArrayRegion to get a double* you can read directly, or GetDoubleArrayElements/ReleaseDoubleArrayElements to manipulate it.

huangapple
  • 本文由 发表于 2020年9月2日 14:40:02
  • 转载请务必保留本文链接:https://go.coder-hub.com/63700016.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定