android - 在 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 是否或如何保证这一点,我仍然有兴趣知道。
解决方案
推荐阅读
- javascript - 在第一次“滴答”之前设置进度条的宽度(倒计时)(没有额外的库)
- c - 将 uint8_t 转换为十六进制字符串(2 位数字)
- flutter - 如何从 Flutter Web 中的 Text 小部件中选择和复制文本?
- java - 我有多个线程,但它们没有一起工作
- go - 使用 range for 循环遍历所有方法
- php - 如何修复在 PHP foreach 循环中错误循环的 jQuery 代码
- sql - 不使用标志计算所有班次的出勤时间
- jquery - ajax 调用中的 jQuery load() 函数不适用于脚本
- database - DB(例如oracle)如何为字符串字段创建索引?
- ios - iOS - watchOS App 发布问题 CFBundleIdentifier 冲突