Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use a simple c++ class in Android NDK

I'm trying to learn the basics of Android NDK but I'm stucked when I have to use it with a c++ class.

I understand how to use it with a simple function but what should I do to be able to manipulate the fields and the methods of a c++ class ?

I'm trying to do it with this simple c++ class :

#include <cstdlib>
#include <jni.h>
using namespace std;


class Point {
   int x, y; // coordonnées du point

   public:
      Point() {
         this->x = 0;
         this->y = 0;
      }

      Point(int x, int y) {
         this->x = x;
         this->y = y;
      }

      int getX() const {
         return x;
      }

      int getY() const {
         return y;
      }

      Point symetrique() const {
         return Point(-x, -y);
      }

      bool operator ==(const Point &p) const {
         return this->x == p.getX() && this->y == p.getY();
      }
};

extern "C" {
    JNIEXPORT jlong JNICALL Java_com_example_jnipoint_JPoint_createPoint__
      (JNIEnv *, jobject);

    JNIEXPORT jlong JNICALL Java_com_example_jnipoint_JPoint_createPoint__II
      (JNIEnv *, jobject, jint, jint);

    JNIEXPORT jint JNICALL Java_com_example_jnipoint_JPoint_nativeGetX
      (JNIEnv *, jobject, jlong);

    JNIEXPORT jint JNICALL Java_com_example_jnipoint_JPoint_nativeGetY
      (JNIEnv *, jobject, jlong);

    JNIEXPORT jlong JNICALL Java_com_example_jnipoint_JPoint_nativeSymetrique
      (JNIEnv *, jobject, jlong);
};


JNIEXPORT jlong JNICALL Java_com_example_jnipoint_JPoint_createPoint__(JNIEnv* env, jobject thiz) {
    return (jlong)(new Point());
}

JNIEXPORT jlong JNICALL Java_com_example_jnipoint_JPoint_createPoint__II(JNIEnv* env, jobject thiz, jint x, jint y) {
    return (jlong)(new Point(x, y));
}

JNIEXPORT jint JNICALL Java_com_example_jnipoint_JPoint_nativeGetX(JNIEnv* env, jobject thiz, jlong nativePointer) {
    return ((Point*)nativePointer)->getX();
}

JNIEXPORT jint JNICALL Java_com_example_jnipoint_JPoint_nativeGetY(JNIEnv* env, jobject thiz, jlong nativePointer) {
    return ((Point*)nativePointer)->getY();
}

jlong Java_com_example_jnipoint_JPoint_nativeSymetrique(JNIEnv* env, jobject thiz, jlong nativePointer) {
    return ((Point*)nativePointer)->symetrique();
}

I tried to find samples but nothing so far... Maybe I'm not using the right keywords

* UPDATE *

I created a Java wrapper for the c++ Point class and added to the c++ file JNI methods. The code is the following :

public class JPoint {

    private long nativePointer;

    public JPoint() {
        nativePointer = createPoint();
    }

    public JPoint(int x, int y) {
        nativePointer = createPoint(x, y);
    }

    public int getX() {
        return nativeGetX(nativePointer);
    }

    public int getY() {
        return nativeGetY(nativePointer);
    }

    public JPoint symetrique() {
        JPoint tmp = new JPoint();
        tmp.nativePointer = nativeSymetrique(nativePointer);
        return tmp;
    }

    // TODO
    /*public boolean equals(Object o) {
        return nativeEquals(o);
    }*/

    private native long createPoint(); // Void constructor
    private native long createPoint(int x, int y);
    private native int nativeGetX(long nativePointer);
    private native int nativeGetY(long nativePointer);
    private native long nativeSymetrique(long nativePointer);
    //private native boolean nativeEquals(Object p); TODO
}

Right now I'm stucked with the nativeSymetrique function, it says that I cannot convert 'Point' to 'jlong'. Can anyone help me on this ? Thanks

* UPDATE 2 *

SWIG solved my issues, you don't have to handwrite the wrappers and it seems to be a good choice for big libraries.

like image 744
Fr4nz Avatar asked Dec 13 '12 14:12

Fr4nz


People also ask

How do I add C++ code to an android project?

You can add C and C++ code to your Android project by placing the code into a cpp directory in your project module. When you build your project, this code is compiled into a native library that Gradle can package with your APK.

What C++ libraries are supported by the Android NDK?

LLVM's libc++ is the C++ standard library that has been used by the Android OS since Lollipop, and as of NDK r18 is the only STL available in the NDK. Note: See the C++14 Status, C++17 Status, and C++2a Status pages for full details of the expected level of C++ library support for any given version.

What is the NDK in Android?

The NDK is a toolset that enables the development of Android apps using C, C++ and other native code languages, compiling code into applications that can run on Android devices. Using the NDK is generally not recommended because apps may experience a performance hit, suffer from compatibility issues, be harder to debug, and reduce flexibility.

Can we use C library in Android app?

We have an Android app here, that consumes a C library, yet it is the app that defines the interface, that the C library should provide. That would be a big issue if one member of your team would write C library, and another would write the Kotlin/Java code.


1 Answers

Have a look at JNA.

JNI is meant to access Java classes/objects from C. Which means that JNI gives you C functions for accessing JVM. But there is no way vice versa: to access C structures (C++ classes) from JVM. Java has no such methods. So if you want to have a "class reflection" between C++ and Java, the only you can do is to have the class on Java side and a set of JNI C calls to access, modify and call methods on the Java object. JNI native methods on Java side are of no use for you, because the only parameters it can take (in or out) can be again only Java objects (or primitives or arrays). There is simply no way to pass C(++) structures/objects to Java side.

like image 145
Pavel Zdenek Avatar answered Oct 09 '22 18:10

Pavel Zdenek