1

我想我知道该怎么做,我只是想戳一下 SO 社区,看看我是否走在正确的轨道上,因为我没有从我的研究中看到任何关于这个特定主题的信息。

我有一些自定义 Java(数据模型)类,我希望在我的应用程序的本机 C++ 端可以访问这些类。我意识到这两个环境是相当独立的,所以我很可能必须在 c++ 中创建我的数据模型的“副本”,并在我的 nativeLib JNI 文件中初始化它们?

我假设我不能只是将 java 类“转换”为 c++ 类,因为编译器可能无法进行这样的转换。我必须通过 JNI 方法调用手动管理我需要的每个字段。

这是正确的,还是有更好的方法我不知道?

我想一个例子可能是这样的:

Foo.java

public class Foo {
    boolean A;
    boolean B;
    boolean C;
}

本机 lib.cpp

extern "C" {

    std::unique_ptr<Foo> foo;

    JNIEXPORT void JNICALL
    Java_com_example_user_project_native_1Foo(JNIEnv *env, jobject instance, jbool jbooleanA, jbool jbooleanB, jbool jbooleanC) {

    Foo->setA(jbooleanA);
    Foo->setB(jbooleanB);
    Foo->setC(jbooleanC);
}

Foo.h

class Foo {
private:
    bool A;
    bool B;
    bool C;

public:
    // add setters & getters here, or any other needed functions
}
4

2 回答 2

0

我假设我不能只是将 java 类“转换”为 c++ 类,因为编译器可能无法进行这样的转换。

你的假设是对的。如果您寻求在本机和 Java 之间实现代理类的自动化,请查看SWIG。它能够扫描头文件并构建将本机类公开给 JVM 的包装器 (.cpp + .java) 代码。这不是您要问的,但可能非常接近。

于 2019-08-30T01:58:29.133 回答
0

在找到我的问题的解决方案时,我发现了有关转换不起作用的更多细节:

  1. ArrayList(来自 Java)在 JNI 框架中不被视为一个 jobjectArray。它被识别为 jObject。所以如果你想转换一个 ArrayList 对象,你必须在 JNI 中创建一个新的 jobjectArray

  2. 您不能访问 ArrayList 类中的方法(如 get 或 set),因为参数类是泛型的。JNI 中不允许使用泛型

由于这两个原因,无法通过 JNI 转换和发送 ArrayList 对象。相反,我选择将我的 ArrayList 转换为myClass[]Java 端的对象数组,然后将其发送出去。

下面是我为此转换编写的代码:

java类.java

void setFooArray(ArrayList<Foo> param) {
    Foo[] fooArray = new Foo[param.size()];

    for (int i = 0; i < param.size(); i++) {
        fooArray[i] = param.get(i);
    }

    native_setFooArray(fooArray, fooArray.length);
}

// ...

private native void native_setFooArray(Foo[] fooArray, int size);

本机 lib.cpp

JNIEXPORT void JNICALL
java_com_example_my_project_native_1setFooArray(JNIEnv *env, jobject instance, jobjectArray fooArray, jint arraySize) {

    std::vector<Foocpp> cfooArray;

    jfieldID fidA;
    jfieldID fidB;

    for (jint i = 0; i < arraySize; i++) {
        jobject jfoo = env->GetObjectArrayElement(fooArray, i);
        jclass cfoo = env->GetObjectClass(jfoo);

        fidA = env->getFieldID(cfoo, "A", "I");
        fidB = env->GetFieldID(cfoo, "B", "I");
        jint A = env->GetIntField(cfoo, fidA);
        jint B = env->GetIntField(cfoo, fidB);

        const Foocpp foo = Foocpp(A, B);
        cfooArray.push_back(foo);
    }

    class->setFooArray(cfooArray);

有用的链接:

于 2019-09-12T07:09:57.887 回答