将自定义 Java 数据模型传递给我的本机代码

Passing Custom Java Data Models to my Native Code

本文关键字:我的 本机代码 自定义 Java 数据模型      更新时间:2023-10-16

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

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

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

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

我想一个例子可能看起来像这样:

福.java

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

原生库.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);
}

福.h

class Foo {
private:
bool A;
bool B;
bool C;
public:
// add setters & getters here, or any other needed functions
}

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

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

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

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

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

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

波纹管是我为此转换编写的代码:

javaClass.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);

原生库.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);

有用的链接:

  • https://www3.ntu.edu.sg/home/ehchua/programming/java/JavaNativeInterface.html#zz-6。

  • https://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/types.html

  • 示例用法:https://gist.github.com/qiao-tw/6e43fb2311ee3c31752e11a4415deeb1