android - 何时在 Android NDK 中使用 JNIEXPORT 和 JNICALL?

标签 android c++ macros android-ndk java-native-interface

我正在尝试编写自己的 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/

相关文章:

visual-studio-code - vscode 如何打印(或粘贴)所有打开的文件路径到编辑器中的新文件?

android - Flutter SQFlite 一对多关系设置

java - 将 Intent 转换为字符串,反之亦然

android - 如何在应用程序的所有 Activity 中播放音乐?

java - java和C++之间的字符串大小关系

c++ - OpenGL 文本渲染方法和权衡

javascript - jsoup 以键值对的形式从网页检索数据

c++ - 赋值运算符左边的三元条件运算符

用于访问 COM 对象属性的 C++ 包装函数(宏)

c++ - 通过 Makefile 的预处理器宏定义在 C++ 中无法正常工作