在Android NDK中使用简单的C++类

7

我想学习Android NDK的基础知识,但在使用它与C++类一起时遇到了困难。

我知道如何使用它来处理简单函数,但应该怎样才能操纵C++类的字段和方法?

我正在尝试使用这个简单的C++类:

#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();
}

我尝试找到样例,但目前没有发现...也许是我没有使用正确的关键词。
*更新*
我创建了一个Java包装类来包裹c++中的Point类,并添加了JNI方法到c++文件。代码如下:
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
}

现在我卡在了nativeSymetrique函数上,它说我不能将“Point”转换为“jlong”。有人能帮我解决这个问题吗?谢谢。

*更新2*

SWIG解决了我的问题,你不需要手写封装器,对于大型库来说,它似乎是一个不错的选择。


好问题,如果你可以在“main()”中使用一些东西,那么你也可以在main中编写一些调用类函数的函数,这是非常糟糕的方法,但也许它可以帮助你 :) - Hayk Nahapetyan
你使用JNI吗?JNI包装器在你的代码中哪里? - dilix
是的,我计划使用JNI,但这段代码只是一个简单的C++类。我想知道在哪里以及如何将JNI与该代码结合使用。 - Fr4nz
3个回答

1

看看 JNA

JNI 用于从C访问Java类/对象。这意味着JNI为您提供了用于访问JVM的C函数。但是没有反向方式:无法从JVM访问C结构(C++类)。 Java没有这样的方法。因此,如果要在C ++和Java之间进行“类反射”,唯一可以做的就是在Java侧具有类,并使用一组JNI C调用来访问,修改和调用Java对象上的方法。 Java侧的JNI本地方法对您没有用处,因为它只能接受(入或出)Java对象(原语或数组),因此根本无法将C(++)结构/对象传递到Java侧。


谢谢你的回答,我会看一下JNA。 - Fr4nz
根据这篇文章https://dev59.com/-3I_5IYBdhLWcg3wBuX3 ,由于C ++的原因,JNA不适合我的用途。 - Fr4nz
JNA 是从 Java 中访问本机对象的最佳选择。JNI 并没有提供任何东西,Java 本身也没有。因此,如果您无法使用 JNA,则第二段,特别是其中的最后一句话,就是我的答案。 - Pavel Zdenek

0
你可以随心所欲地操作你的C代码,并通过JNI传递\返回值,你可以在androidndk/samples - helloJni中找到JNI示例。
例如:
JNIEXPORT jfloat JNICALL Java_com_opengl_glworld_GLWorldRenderer_changeCurrentArea(JNIEnv *env, jobject obj, jfloat curArea)
{
    area = curArea;
    return area;
    // here you can execude you C code, you can access to methods of class,
    // or method  that use your classes.
}

我知道我必须使用JNI,我读了那些示例,但是关于C++类和JNI呢?你是说我需要为我的Point类的每个方法编写一个JNI函数吗?并且我还需要在Java端创建一个类似的类(Point),其中包含本地方法吗? - Fr4nz
你想从Java传递对象到C++吗?请查看这个答案https://dev59.com/q2855IYBdhLWcg3wNxgM,而且谷歌可以帮助你在JNI中传递对象 =) - dilix
https://dev59.com/JXE95IYBdhLWcg3wApBU - dilix

0

正如我在第二次更新中所说,SWIG 是我需求的完美匹配。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接