将自定义Java数据模型传递到本机代码

将自定义Java数据模型传递到本机代码,java,android,c++,java-native-interface,android-native-library,Java,Android,C++,Java Native Interface,Android Native Library,我想我知道该怎么做了,我只是想打探一下SO社区,看看我是否走上了正确的道路,因为我还没有从我的研究中看到关于这个特定主题的任何信息 我有一些自定义java(数据模型)类,我希望在我的应用程序的本机C++侧访问。我意识到这两个环境是完全独立的,所以我将不得不在C++中创建我的数据模型的“复制”,并在我的NITIVIB JNI文件中初始化它们。 我假设我不能仅仅把java类转换成C++类,因为编译器可能无法进行这样的转换。我必须通过JNI方法调用手动管理我需要的每个字段 这是正确的,还是我不知道有更

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

<>我有一些自定义java(数据模型)类,我希望在我的应用程序的本机C++侧访问。我意识到这两个环境是完全独立的,所以我将不得不在C++中创建我的数据模型的“复制”,并在我的NITIVIB JNI文件中初始化它们。 我假设我不能仅仅把java类转换成C++类,因为编译器可能无法进行这样的转换。我必须通过JNI方法调用手动管理我需要的每个字段

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

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

Foo.java

public class Foo {
    boolean A;
    boolean B;
    boolean C;
}
native-lib.cpp

extern“C”{
std::唯一的\u ptr foo;
JNIEXPORT void JNICALL
Java_com_示例_用户_项目_本地_1Foo(JNIEnv*env、jobject实例、jbool jbooleanA、jbool jbooleanB、jbool jbooleanC){
Foo->setA(jbooleanA);
Foo->setB(jbooleanB);
Foo->setC(jbooleanC);
}
福安

class-Foo{
私人:
布尔A;
布尔B;
布尔C;
公众:
//在此处添加setter和getter,或者添加任何其他需要的函数
}
我假设我不能仅仅把java类转换成C++类,因为编译器可能无法进行这样的转换。 您的假设是正确的。如果您希望在本机和Java之间实现代理类的自动化,请看一看。它能够扫描头文件并构建将本机类公开给JVM的包装器(.cpp+.Java)代码。这并不完全是您要问的,但可能非常接近

我假设我不能仅仅把java类转换成C++类,因为编译器可能无法进行这样的转换。
您的假设是正确的。如果您希望在本机和Java之间实现代理类的自动化,请看一下。它能够扫描头文件并构建包装(.cpp+.Java)将本机类公开给JVM的代码。这不完全是您要问的,但可能非常接近。

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

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

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

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

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

    javaClass.java

    void setFooArray(ArrayList参数){
    Foo[]fooArray=新的Foo[param.size()];
    对于(int i=0;i
    本机lib.cpp

    JNIEXPORT void JNICALL
    java_com_示例_my_project_native_1setFooArray(JNIEnv*env、jobject实例、jobjectArray fooArray、jint arraySize){
    std::向量cfoo阵列;
    jfieldID-fidA;
    jfieldID-fidB;
    对于(jint i=0;iGetObjectArrayElement(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);
    
    有用的链接:

    • 用法示例:


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

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

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

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

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

    javaClass.java

    void setFooArray(ArrayList参数){
    Foo[]fooArray=新的Foo[param.size()];
    对于(int i=0;i
    本机lib.cpp

    JNIEXPORT void JNICALL
    java_com_示例_my_project_native_1setFooArray(JNIEnv*env、jobject实例、jobjectArray fooArray、jint arraySize){
    std::向量cfoo阵列;
    jfieldID-fidA;
    jfieldID-fidB;
    对于(jint i=0;iGetObjectArrayElement(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);
    常数