Обновить вложенные объекты Java из C - PullRequest
0 голосов
/ 21 июня 2019

Я хочу передать структурный указатель из 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);

Ответы [ 2 ]

2 голосов
/ 21 июня 2019

В двух словах, вам нужно сделать следующее:

// 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] на самом деле являются строками с нулевым символом в конце, вам лучше преобразовать их в строку и использовать NewStringUTF на стороне C ++.

РЕДАКТИРОВАТЬ: ответ выше C ++ вместо C, но это в основном косметическое (env->Method(ARGS) должно быть (*env)->Method(env, ARGS)

РЕДАКТИРОВАТЬ 2: Из вашего вопроса не ясно, находится ли ваш Java-код в пространстве имен. Если это так, вам может понадобиться pkg/path/to/MyOuterClass$struct1.

РЕДАКТИРОВАТЬ 3: Исправлена ​​модификация .d

1 голос
/ 21 июня 2019

Вы можете использовать Scapix Java Link для генерации заголовков C ++ для ваших классов Java, тогда манипулирование объектами Java из C ++ становится очень простым:

#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);
    }
}

Для получения дополнительной информации см. пример2

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...