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

时间:2011-09-24 23:12:46

标签: android java-native-interface

我想访问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

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]?? 


}`

1 个答案:

答案 0 :(得分:0)

也许你需要分配数组来开始。

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

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

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 =新AA [num_states];

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

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