0

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 (Get java array from c++ via JNI), 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 <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());

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

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

Java code:

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();
}
1
  • 1
    I think passing variables/inputs back and forth is fine but it shouldn't be too much complex (model classes), because then it would arise complexity on native side parsing and generating it. Even though I would suggest to follow this link as reference just in case: docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/… Commented Sep 2, 2020 at 6:51

1 Answer 1

1

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->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.

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you very much for your insight. Where does the signature ()[D go? Where I currently have ()[java/lang/Double ? Sorry...not terribly familiar with C++ so I am struggling my way through this conversion process.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.