将自定义 Java 数据模型传递到我的本机代码
Passing Custom Java Data Models to my Native Code
我想我知道该怎么做,我只是想看看 SO 社区,看看我是否走在正确的轨道上,因为我没有从我的研究中看到关于这个特定主题的任何信息。
我有一些自定义 Java(数据模型)classes,我想在我的应用程序的本机 C++ 端访问它们。我意识到这两个环境是相当独立的,所以我很可能必须在 c++ 中创建一个 "copy" 我的数据模型,并在我的 nativeLib JNI 文件中初始化它们?
我假设我不能 "convert" java class 到 c++ class,因为编译器可能无法做到这样的转换。我将不得不通过 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
}
I'm assuming I can't just "convert" the java class to the c++ class, since the compiler probably won't be able to do such a conversion.
你的假设是对的。如果您寻求在本机和 Java 之间自动代理 classes,请查看 SWIG。它能够扫描头文件并构建包装器 (.cpp + .java) 代码,将本机 class 公开给 JVM。这不是您要问的确切内容,但可能非常接近。
在寻找我的问题的解决方案时,我发现了有关为什么转换不起作用的更多细节:
ArrayList(来自 Java)在 JNI 框架中未被视为 jobjectArray。它被识别为 jObject。因此,如果您想转换 ArrayList 对象,则必须在 JNI
中创建一个新的 jobjectArray
您不能访问 ArrayList class 中的方法(如 get 或 set),因为参数的 class 是通用的。 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);
原生-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);
有用链接:
我想我知道该怎么做,我只是想看看 SO 社区,看看我是否走在正确的轨道上,因为我没有从我的研究中看到关于这个特定主题的任何信息。
我有一些自定义 Java(数据模型)classes,我想在我的应用程序的本机 C++ 端访问它们。我意识到这两个环境是相当独立的,所以我很可能必须在 c++ 中创建一个 "copy" 我的数据模型,并在我的 nativeLib JNI 文件中初始化它们?
我假设我不能 "convert" java class 到 c++ class,因为编译器可能无法做到这样的转换。我将不得不通过 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
}
I'm assuming I can't just "convert" the java class to the c++ class, since the compiler probably won't be able to do such a conversion.
你的假设是对的。如果您寻求在本机和 Java 之间自动代理 classes,请查看 SWIG。它能够扫描头文件并构建包装器 (.cpp + .java) 代码,将本机 class 公开给 JVM。这不是您要问的确切内容,但可能非常接近。
在寻找我的问题的解决方案时,我发现了有关为什么转换不起作用的更多细节:
ArrayList(来自 Java)在 JNI 框架中未被视为 jobjectArray。它被识别为 jObject。因此,如果您想转换 ArrayList 对象,则必须在 JNI
中创建一个新的 jobjectArray
您不能访问 ArrayList class 中的方法(如 get 或 set),因为参数的 class 是通用的。 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);
原生-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);
有用链接: