首页 > 解决方案 > 在 Android 上通过 RegisterNatives() 在 C++ 中注册 JNI 本机函数的可移植性

问题描述

在 JNI 中注册本机函数的方法之一是使用 function 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()需要将(非成员)函数指针转换为 type void*,如上所示。根据这个文档,这在 C++ 中不一定是可移植的。它可以保证在某些环境(例如 POSIX)中工作,但其行为是依赖于实现的。

如果它不可靠,我不希望以这种方式公开此功能,但是 JNI 或 Android 是否提供任何保证可以依靠它来工作?是否只是假设 JNI 和/或 Android 将始终在void*支持函数指针之间转换的环境中运行?

编辑:

经过进一步考虑,似乎 JNI 几乎不得不对本机函数做一些不可移植的事情,而不管演员表的问题。关于函数 JNI 的唯一信息(地址除外)是描述参数和返回类型的字符串,因此似乎不太可能void*将其转换回有效的函数指针并以传统方式使用。据推测,这些调用是通过低级特定于平台的代码进行的。

函数指针强制转换似乎仍然是一个要求void*,所以如果有人知道 JNI 是否或如何保证这一点,我仍然有兴趣知道。

标签: androidc++java-native-interface

解决方案


推荐阅读