我正在尝试编写自己的 jni 资源。查看一些 ndk 示例,我发现他们经常使用这些宏 JNIEXPORT 和 JNICALL 后跟 java 包的名称这样的
JNIEXPORT void JNICALL Java_com_example_plasma_PlasmaView_renderPlasma(JNIEnv * env, jobject obj, jobject bitmap, jlong time_ms)
我用谷歌搜索了,但我不明白何时以及如何使用这些宏
最佳答案
JNIEXPORT 和 JNICALL 在 NDK_ROOT/platforms/android-9/arch-arm/usr/include/jni.h 中定义。根据您的设置,此路径会有所不同,但大多相似。
#define JNIIMPORT
#define JNIEXPORT __attribute__ ((visibility ("default")))
#define JNICALL
JNIEXPORT 用于使本地函数出现在构建的二进制文件(*.so 文件)的动态表中。它们可以设置为“隐藏”或“默认”(更多信息 here)。如果这些函数不在动态表中,JNI 将无法找到调用它们的函数,因此 RegisterNatives 调用将在运行时失败。
值得注意的是,默认情况下,所有函数最终都在动态表中,因此任何人都可以很容易地反编译您的 native 代码。每个函数调用都内置在二进制文件中,以防 JNI 需要找到它。这可以使用编译器选项 -fvisibility
进行更改。我建议大家将其设置为 -fvisibility=hidden
以确保您的代码安全,然后使用 JNIEXPORT 将函数标记为具有外部可见性。
使用 strip 命令只是删除调试符号,动态表是独立的。玩 objdump 看看一个人可以从你的 .so 文件中得到多少。
我们最近被这个绊倒了,希望这对某人有所帮助。
编辑:我们使用自定义构建系统,因此默认情况下可以为其他build设置设置可见性选项。更多信息请访问 this SO answer .
关于android - 何时在 Android NDK 中使用 JNIEXPORT 和 JNICALL?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19422660/