Stam
Stam

Reputation: 2490

What is the most effective way to pass a C++ Object to Java using Android NDK

I am using Android NDK and I want to pass some intances of a C++ Object (let's say it is called Point) in Java, so I can populate a ListView with them. I found two solutions and I would like to find out which is the best.

1 solution:

Creating a Point.cpp and a JPoint.class and using the following method in a cpp file:

JNIEXPORT jobject JNICALL  Java_com_example_jnisqliteexperiment_MainActivity_getPersons(
        JNIEnv *env,
        jobject callingObject)
{
Point* point = new Point();
    point->setX(12);
    point->setY(20);
    x=point->getX();
    y=point->getY();
jclass cls = env->FindClass("com/example/myproject/JPoint");
constructor = env->GetMethodID( cls, "<init>", "(II)V");
jobject obj = env->NewObject(cls, constructor, x, y); //creates a new JPoint(12,20)
return obj;
}

2 solution:

Creating JSON parser like EasyNDK, so I can send those instances from C++ to Java via a String.

  1. Which of them is the most effective way, since I would like to populate my ListView with 100 or more of those instances?

  2. What about FindClass method? Since it tries to find a path, isn't it too slow?

Upvotes: 0

Views: 1508

Answers (2)

fadden
fadden

Reputation: 52313

It's hard to say what's "best" without knowing what your criteria are. Performance? Ease of use?

Both approaches are somewhat heavyweight. In the first you're allocating an object, looking up the class and constructor, and invoking the constructor on every call. In the second you're adding the overhead of creating and parsing JSON data.

You can optimize #1 by caching the result of FindClass in a JNI global reference, and the result of GetMethodID in a simple global. If your data is actually as simple as it appears in your example, with just X and Y values, you don't need to pass an object around at all -- just pass in an int[2] and store the values in the array. That would reduce your overhead to a single SetIntArrayRegion.

If you really want to pass data through an object -- maybe it's more complex than a pair of integers -- you can avoid the allocation by repeatedly passing a re-usable object into your native method. The native method populates the object and hands it back.

If that's still too much overhead, you can use other tricks, like creating parallel arrays and passing those around (i.e. an array with all the X coordinates, and an array with all the Y coordinates). This reduces your overhead to one set of array allocations and one method call for the whole set so long as you're just working with primitive types. If there's an upper bound on the number of points you can pre-allocate the arrays and completely avoid allocations. As your objects become more complex this becomes more unwieldy.

Upvotes: 2

Entreco
Entreco

Reputation: 12900

I don't have experience with EasyNDK, but both solutions look fine.

1) Since I don't know EasySDK, I don't know which one is most effective. As far as I can tell, easyNDK will create a JSON for your object, sends that JSON to the java side, and creates a java object from it. It seems like an easy solution indeed, but I would think that it is slightly more overhead than creating the Java objects directly from your c++ code.

2) FindClass is relatively expensive, so make sure you call it once (e.g. at startup) and store the returned jclass object somewhere in your c++ code. I have used FindClass in some projects to create java objects from c++ code. For my purpose it was not too slow, and gave good performance. You should check that the calls are fast enough for your project, but I believe it will not be a problem.

Good luck

Upvotes: 0

Related Questions