如何使用 SetArrayRegion 将数组从 C 结构映射到 Java 类数组?

发布于 2024-12-06 11:33:55 字数 1447 浏览 1 评论 0原文

我想访问 C 结构体(如下)的数据成员并将它们映射到我的 java 类中的数组上。我尝试使用 Set<>ArrayRegion 来映射值,但我在某个地方出错了。下面是我正在尝试做的事情的一个例子。有人可以帮助我使用正确的语法来映射值吗?

c 标头

`

typedef struct a {
    long                            nls;
    uint8_t                         *lane; 
    long                            t; 

} aa;

typedef struct b {
    uint32_t                        id; 
    uint64_t                        timestamp_ms;
    long                            num_states;
    aa                      *move_states; 
} bb;

java 类

class J {
    int     i_id; 
    long        timestamp_ms; 
    long        num_states;
    long[]      nls;
    long[][]    lane;
    long[]      t;      

    }

test.c

JNIEXPORT jint JNICALL Java_com_android_...
  (JNIEnv *env, jclass c, jobject obj)
{


    bb  c_struct;

    // do some operations on c_struct to populate the structure

    ....


    J   java_class;
    jFieldID fid;
    jclass cls = (*env)->GetObjectClass(env,obj);


    fid=(*env)->GetFieldID(env,cls,"i_id","I");
    (*env)->SetIntField(env,obj,fid,c_struct.id);

    ... similar for timestamp_ms,num_states


    // how do I map c_struct->move_states[i].nls to java_class.nls[i] ??
    // also how do I map c_struct->move_states[i].lane[j] to java_class.lane[i][j]?? 


}`

I want to access data members of a C struct(below) and map them onto an array in my java class. I have tried to used Set<>ArrayRegion to map the values but I am going wrong somewhere. Below is an example of what I am trying to do. Can somebody please help me with the correct syntax to map the values?

c header

`

typedef struct a {
    long                            nls;
    uint8_t                         *lane; 
    long                            t; 

} aa;

typedef struct b {
    uint32_t                        id; 
    uint64_t                        timestamp_ms;
    long                            num_states;
    aa                      *move_states; 
} bb;

java class

class J {
    int     i_id; 
    long        timestamp_ms; 
    long        num_states;
    long[]      nls;
    long[][]    lane;
    long[]      t;      

    }

test.c

JNIEXPORT jint JNICALL Java_com_android_...
  (JNIEnv *env, jclass c, jobject obj)
{


    bb  c_struct;

    // do some operations on c_struct to populate the structure

    ....


    J   java_class;
    jFieldID fid;
    jclass cls = (*env)->GetObjectClass(env,obj);


    fid=(*env)->GetFieldID(env,cls,"i_id","I");
    (*env)->SetIntField(env,obj,fid,c_struct.id);

    ... similar for timestamp_ms,num_states


    // how do I map c_struct->move_states[i].nls to java_class.nls[i] ??
    // also how do I map c_struct->move_states[i].lane[j] to java_class.lane[i][j]?? 


}`

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

墨小沫ゞ 2024-12-13 11:33:55

也许您需要首先分配数组。

这意味着使用 NewLongArray() 创建足够长度的数组对象,使用 SetLongArrayRegion() 填充数组对象,然后使用 SetObjectField() 将新数组实例设置为 java 对象(丢弃旧数组)。

您可以通过确保在调用 JNI 填充数组之前在 Java 中分配足够大的数组来快速测试该理论。

int SIZE = 1000;  // make this big enough
J j = new J();
j.nls = new long[SIZE];
j.lane = new long[SIZE][SIZE];  // something like this multi-dimention array
j.t = new long[SIZE];
int i = callMyJniMethod(j);

现在尝试您的 GetField、SetLongArrayRegion 想法。确保 num_states < 1000.

一旦您证明这一点可以开始工作,您就可以研究您希望 API 究竟如何工作。对此的想法:

  • 保留当前设计,但让 JNI 分配数组。

  • 创建一个新的 Java 对象“AA”,并让 JNI 为每个 C++“aa”设置一个并填充它,然后将 BB(又名 J)数组附加到 J 对象。 j.aa = new AA[num_states];

FWIW您正在尝试在C ++ / Java之间复制数据(不是映射,因为术语映射的使用意味着某种共享,更新一个不会更新另一个,除非您重新复制)

FWIW C / C ++中的“长”可能是32位在您的平台上,但 Java 上的“long”始终是 64 位。

Maybe you need to allocate the array to start with.

This means creating the array object with enough length NewLongArray(), using SetLongArrayRegion() to fill the array object, then using SetObjectField() to set the new array instance into java object (disarding the old one).

You can test this theory out quickly by ensuring in Java you allocate a big enough array before calling your JNI to fill it.

int SIZE = 1000;  // make this big enough
J j = new J();
j.nls = new long[SIZE];
j.lane = new long[SIZE][SIZE];  // something like this multi-dimention array
j.t = new long[SIZE];
int i = callMyJniMethod(j);

Now try your GetField, SetLongArrayRegion ideas. Making sure that num_states is < 1000.

Once you have proven this to start working, you can work on how exactly you want your API to work. Ideas on this:

  • Keep your current design, but have JNI allocate the array.

  • Create a new Java object "AA" and have JNI instate one for each C++ "aa" and fill it in, and then attach an array of BB (aka J) to the J object. j.aa = new AA[num_states];

FWIW you are trying to copy the data between C++/Java (not map, as use of term map implies some kind of sharing, updating one will not update the other unless you re-copy)

FWIW "long" in C/C++ maybe 32bit on your platform, but "long" on Java is always 64bit.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文