Переносимость регистрации собственных функций JNI через RegisterNatives () в C ++ на Android - PullRequest
1 голос
/ 04 февраля 2020

Одним из способов регистрации собственных функций в JNI является использование функции RegisterNatives(). Пример (хотя и с некоторыми ошибками) можно найти в Android документации здесь . Вот пример кода, демонстрирующий эту технику:

#include <jni.h>

void JNICALL test(JNIEnv* const environment, jobject const objectOrClass) {
}

extern "C" JNIEXPORT jint JNI_OnLoad(JavaVM* const vm, void* const reserved) {
    JNIEnv* environment;

    vm->GetEnv(reinterpret_cast<void**>(&environment), JNI_VERSION_1_6);

    auto const classRef = environment->FindClass("com/example/test/MainActivity");

    JNINativeMethod method;

    method.name = "test";
    method.signature = "()V";
    method.fnPtr = reinterpret_cast<void*>(test);

    environment->RegisterNatives(classRef, &method, 1);

    return JNI_VERSION_1_6;
}

Использование RegisterNatives() требует, чтобы указатели на функции (не являющиеся членами) указывали на void*, как показано выше. Согласно этой документации , это не обязательно переносимо в C ++. Может быть гарантированно работать в некоторых средах (например, POSIX), но в остальном поведение зависит от реализации.

Я бы не ожидал, что эта функциональность будет раскрыта таким образом, если она ненадежна, но JNI или Android предлагают какие-либо гарантии того, что на это можно рассчитывать? Предполагается ли, что JNI и / или Android всегда будут работать в средах, где поддерживается приведение между указателями на функции и void*?

РЕДАКТИРОВАТЬ:

После дальнейшего рассмотрения кажется, что JNI почти придется делать что-то непереносимое по отношению к нативным функциям, независимо от проблемы приведения. Единственной информацией о функции, которую имеет JNI (кроме адреса), является строка, описывающая аргументы и возвращаемые типы, поэтому маловероятно, что void* когда-либо будет приведен обратно к действительному указателю на функцию и использован обычным способом. Предположительно, вместо этого вызовы выполняются с помощью низкоуровневого кода c, определяемого платформой.

По-прежнему кажется необходимым, чтобы функция-указатель на void* приводила себя хорошо, поэтому, если кто-то знает, если или как JNI гарантирует это, мне все равно было бы интересно узнать.

...