从 C 更新嵌套的 java 个对象
Update nested java objects from C
我想将一个结构指针从 Java 传递给 c,它会在其中更新为所需的值,并在我的 java 代码中使用这些值。我在整个互联网上进行了搜索,但找不到任何需要的页面,也找不到任何好的示例。请帮我解决一下这个。我是 Java/JNI.
的新手
下面是我使用的 JNI c 文件
typedef struct _struct1{
char a;
char b;
short c;
char d[20];
int e;
int f;
}struct1;
typedef struct _struct2{
struct1 g[12];
}struct2;
JNIEXPORT void JNICALL Java_com_example_test_GetDataFromC(
JNIEnv *env,
jobject /* this */,jobject foo) {
/* I want to update foo with the values from struct2*/
test_application(&struct2);
}
下面是java代码
public class struct1{
public char a;
public char b;
public short c;
public char []d= new char[20];
public int e;
public int f;
}
public class struct2{
public struct1[]g= new struct1[12];
}
protected void onCreate(Bundle savedInstanceState) {
struct2 foo = new struct2();
GetDataFromC(foo);
printf("f = %d \n",foo.g[1].f);
}
public native void GetDataFromC(struct2);
简而言之,您需要执行以下操作:
// Get foo.g
jclass cls_struct2 = env->FindClass("struct2");
jfieldID fld_struct2_g = env->GetFieldID(cls_struct2, "g", "[Lstruct2;");
jarray foo_g = (jarray) env->GetObjectField(foo, fld_struct2_g);
// Look up field IDs of struct1
jclass cls_struct1 = env->FindClass("struct1");
jfieldID fld_struct1_a = env->GetFieldID(cls_struct1, "a", "C");
jfieldID fld_struct1_d = env->GetFieldID(cls_struct1, "d", "[C");
// Loop over the array
jsize s = env->GetArrayLength(foo_g);
for (int i = 0; i < s; i++) {
jobject element = env->GetObjectArrayElement(foo_g, i);
env->SetCharField(element, fld_struct1_a, _struct2[i].a);
jcharArray element_d = (jcharArray) env->GetObjectField(element, fld_struct1_d);
env->SetCharArrayRegion(element_d, 0, sizeof(_struct2[i].d) / sizeof(_struct2[i].d[0]), _struct2[i].d);
}
如果 char[20]
字段实际上是 null-terminated 字符串,您最好将它们转换为字符串并在 C++ 端使用 NewStringUTF
。
编辑:上面的答案是 C++ 而不是 C,但这主要是装饰性的(env->Method(ARGS)
应该是 (*env)->Method(env, ARGS)
编辑 2:根据您的问题,不清楚您的 Java 代码是否在命名空间中。如果是,您可能需要 pkg/path/to/MyOuterClass$struct1
.
编辑 3:更正 .d
的修改
您可以使用 Scapix Java Link 为您的 java 类 生成 C++ headers,然后从 C++ 操作 Java objects 变得非常容易:
#include <example/Access.h> // C++ header generated by scapix_java from Access.class file
#include <example/Access_struct1.h> // C++ header generated by scapix_java from Access$struct1.class file
#include <example/Access_struct2.h> // C++ header generated by scapix_java from Access$struct2.class file
using namespace scapix::java_api;
using namespace scapix::java::link;
void update(ref<example::Access::struct2> s2)
{
for (auto&& s1 : s2->g()->elements())
{
s1->a('A');
s1->b('B');
s1->c(33);
for (auto&& d : s1->d()->elements())
d = 'D';
s1->e(44);
s1->f(55);
}
}
有关详细信息,请参阅 example2
我想将一个结构指针从 Java 传递给 c,它会在其中更新为所需的值,并在我的 java 代码中使用这些值。我在整个互联网上进行了搜索,但找不到任何需要的页面,也找不到任何好的示例。请帮我解决一下这个。我是 Java/JNI.
的新手下面是我使用的 JNI c 文件
typedef struct _struct1{
char a;
char b;
short c;
char d[20];
int e;
int f;
}struct1;
typedef struct _struct2{
struct1 g[12];
}struct2;
JNIEXPORT void JNICALL Java_com_example_test_GetDataFromC(
JNIEnv *env,
jobject /* this */,jobject foo) {
/* I want to update foo with the values from struct2*/
test_application(&struct2);
}
下面是java代码
public class struct1{
public char a;
public char b;
public short c;
public char []d= new char[20];
public int e;
public int f;
}
public class struct2{
public struct1[]g= new struct1[12];
}
protected void onCreate(Bundle savedInstanceState) {
struct2 foo = new struct2();
GetDataFromC(foo);
printf("f = %d \n",foo.g[1].f);
}
public native void GetDataFromC(struct2);
简而言之,您需要执行以下操作:
// Get foo.g
jclass cls_struct2 = env->FindClass("struct2");
jfieldID fld_struct2_g = env->GetFieldID(cls_struct2, "g", "[Lstruct2;");
jarray foo_g = (jarray) env->GetObjectField(foo, fld_struct2_g);
// Look up field IDs of struct1
jclass cls_struct1 = env->FindClass("struct1");
jfieldID fld_struct1_a = env->GetFieldID(cls_struct1, "a", "C");
jfieldID fld_struct1_d = env->GetFieldID(cls_struct1, "d", "[C");
// Loop over the array
jsize s = env->GetArrayLength(foo_g);
for (int i = 0; i < s; i++) {
jobject element = env->GetObjectArrayElement(foo_g, i);
env->SetCharField(element, fld_struct1_a, _struct2[i].a);
jcharArray element_d = (jcharArray) env->GetObjectField(element, fld_struct1_d);
env->SetCharArrayRegion(element_d, 0, sizeof(_struct2[i].d) / sizeof(_struct2[i].d[0]), _struct2[i].d);
}
如果 char[20]
字段实际上是 null-terminated 字符串,您最好将它们转换为字符串并在 C++ 端使用 NewStringUTF
。
编辑:上面的答案是 C++ 而不是 C,但这主要是装饰性的(env->Method(ARGS)
应该是 (*env)->Method(env, ARGS)
编辑 2:根据您的问题,不清楚您的 Java 代码是否在命名空间中。如果是,您可能需要 pkg/path/to/MyOuterClass$struct1
.
编辑 3:更正 .d
您可以使用 Scapix Java Link 为您的 java 类 生成 C++ headers,然后从 C++ 操作 Java objects 变得非常容易:
#include <example/Access.h> // C++ header generated by scapix_java from Access.class file
#include <example/Access_struct1.h> // C++ header generated by scapix_java from Access$struct1.class file
#include <example/Access_struct2.h> // C++ header generated by scapix_java from Access$struct2.class file
using namespace scapix::java_api;
using namespace scapix::java::link;
void update(ref<example::Access::struct2> s2)
{
for (auto&& s1 : s2->g()->elements())
{
s1->a('A');
s1->b('B');
s1->c(33);
for (auto&& d : s1->d()->elements())
d = 'D';
s1->e(44);
s1->f(55);
}
}
有关详细信息,请参阅 example2