Метод QMetaObject InvokeMethod, передающий аргумент целочисленного массива

Я довольно новичок в Qt и пытаюсь заняться разработкой Android. Я работаю с Qt и использую QAndroidJNIEnvironment. В коде я реализую свой родной метод, используя QMetaObject::invokeMethod вызвать слот в заголовке QMainWindow. Проблема в том, что нативный метод в java-файле имеет параметр, который является целочисленным массивом java (эквивалентный тип, который я считаю в QAndroindJniObject - это jintArray). Я не могу найти соответствующий тип C++/Qt для размещения в макросе Q_ARG(тип, значение) для разрешения аргумента. Пожалуйста, помогите мне понять, что я делаю неправильно, так как я думал, что тип, эквивалентный jintArray, был int [], но я получаю ошибку, когда использую это. Заранее спасибо за помощь.

onReceiveNativeMounted (JNIEnv * env, jobject obj,jint array_index,jintArray version)
{

QMetaObject::invokeMethod(&MainWindow::instance(), "onReceiveMounted"
                          , Qt::QueuedConnection, Q_ARG(int, array_index),Q_ARG(int[], version));

 return array_index;
}

ошибка, которую я получаю, ниже:

error: no matching function for call to 
'QArgument<int []>::QArgument(const char [6], _jarray*&)'
 #define Q_ARG(type, data) QArgument<type >(#type, data)
                                                       ^

В соответствии с запросом подпись функции Java ниже:

public static native int onReceiveNativeMounted(int array_index, int[] version);

1 ответ

Вам необходимо получить доступ к массивам Java в соответствии с API JNI. Самое простое, что нужно сделать - это преобразовать данные в QVector, Вам необходимо скопировать массив Java, поскольку его время жизни не находится под вашим контролем (если только вы этого не хотите, но это делает жизнь намного сложнее, чем нужно).

QVector toQVector(JNIEnv * env, jintArray arr) {
  auto len = (*env)->GetArrayLength(env, arr);
  QVector result(len);
  auto data = (*env)->GetIntArrayElements(env, arr, 0);
  for (int i = 0; i < len; ++i)
    result[i] = data[i];
  (*env)->ReleaseIntArrayElements(env, arr, data, 0);
  return result;
}

Это немного более эффективно выполнять вызов непосредственно из функтора, а не через invokeMethod, Функтор может захватить вектор:

int onReceiveNativeMounted (JNIEnv * env, jobject obj, jint array_index, jintArray version)
{
  auto window = &MainWindow::instance();
  auto vector = toQVector(env, version);
  QObject sig;
  sig.connect(&sig, &QObject::destroyed, window, [=]{
    window->onReceiveMounted(array_index, vector.data());
  }, Qt::QueuedConnection);
  return array_index;
}
Другие вопросы по тегам