将自定义 Java 数据模型传递给我的本机代码
Passing Custom Java Data Models to my Native Code
我想我有一个想法该怎么做,我只是想戳一下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。这不是您要问的,但可能非常接近。
在寻找我问题的解决方案时,我发现了转换不起作用的更多细节:
-
ArrayList(来自Java(在JNI框架中不被视为jobjectArray。 它被识别为 jObject。 因此,如果要转换ArrayList对象,则必须在JNI中创建一个新的jobjectArray
。 -
您不能从 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
- 在nodejs中使用本机代码的最佳方法是什么?
- 终止调用本机代码的 .Net 线程
- 从本机代码返回到托管代码会损坏返回的对象
- 我能否通过 JNI 调试在本机代码中创建的 JVM?
- 将自定义 Java 数据模型传递给我的本机代码
- 用于 JUnit 测试的本机代码未使用 'nar-maven-plugin' 编译
- 对于我在 Microsoft Visual C++ IDE (2005 或更高版本)的本机 win32 项目中编写的应用
- 为什么我的SSE代码比本机C++代码慢
- 如果您以Java JNI分配的本机代码中的内存泄漏,会发生什么
- 如何在 Eclipse 中调试 Android 上的 OpenCV 示例的本机代码
- 如何将我在VC++9中开发的带有CLR支持静态库的C++/CLI(托管)链接到我在VC++6.0中的本机代码(应用程序)
- 如何在windows平台上调试android中的本机代码
- Java 端找不到我的本机方法
- 包装在C++/CLI中使用本机接口的本机C++代码
- 调试通过JNI调用的本机代码(并防止JVM在遇到致命错误后中止程序)
- 在Android应用程序开发的本机代码中使用opencv
- Windows RT在ARM上的本机代码调用约定是什么?
- 无法从调用Java代码的本机代码获取类引用
- Windows:当我从本机代码回调到托管代码时,将显示“仅消息”窗口
- 编译windows phone 8的本机代码(c++)