android - 在另一个源文件中调用 JNI C 函数

标签 android c++ c android-studio java-native-interface

我正在尝试从 JNI native-lib.cpp 文件调用 C 函数 foo()。 foo() 在 foo.h 中声明并在 foo.c 中定义。 native-lib.cpp 已经包含“foo.h”,因此 Android Studio 似乎认识到该函数存在,但在构建时,我收到以下错误:

error: undefined reference to 'foo(unsigned char const*, unsigned int*, int)'

foo() 在 foo.h 中声明如下:

void foo(const unsigned char key[], unsigned int w[], int keysize);

foo()在native-lib.cpp中调用如下:

static unsigned char byteArray[32];
unsigned int intArray[64];
foo(byteArray, intArray, 256);

我错过了什么吗?为什么我会收到错误消息?

我还注意到,当我打开 foo.c 时,Android Studio 通知我“此文件不是项目的一部分。请将其包含在适当的构建文件(build.gradle、CMakeLists.txt 或 Android.mk)中等)并同步项目。”我该怎么做?

最佳答案

可能的问题是链接器将您的 foo() 函数识别为 C++ 函数,而不是 C 函数。

由于 C++ 函数可以重载,C++ 编译器会“修改”名称,以便链接器拥有该函数的唯一键。任何遇到 foo.h 的 C++ 模块都会假定该函数是 C++ 函数,因此将对函数名称进行名称修改。

例如,在编译的目标代码中,重整后的名称可能看起来像这样:

foo@ucharp@uintp@int

(每个品牌的C++编译器都有自己的命名方案)。

另一方面,当C编译器遇到foo.h时,编译后的目标代码会生成一个表示“未损坏的”foo的符号> 名称,或多或少,这个:

foo_foo

现在在链接时,由于您从 C++ 代码调用了 foo 函数,链接器将尝试查找损坏的版本,并且由于没有名为 foo 的 C++ 函数code>,您会收到链接器错误。

所以基本上你的 foo.h header 或你对它的使用需要聪明并且适用于 C 模块 C++ 模块,其中C++ 模块知道 foo 引用的是 C 函数,因此不会破坏该名称。

<小时/>

一种方法是将 foo.h 更改为:

#ifdef __cplusplus
extern "C" {
#endif

    void foo(const unsigned char key[], unsigned int w[], int keysize);

#ifdef __cplusplus
}
#endif

所以基本上,当 C 编译器看到 header 时,__cplusplus 并不存在。对于C++模块,定义了__cplusplus,因此extern "C"生效,从而C++模块将foo()识别为C 函数。

如果您无法更改 foo.h,那么您可以在 C++ 模块中用 extern "C" 将其包围:

extern "C" {
  #include <foo.h>
}

See this on more information of __cplusplus

关于android - 在另一个源文件中调用 JNI C 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53624310/

相关文章:

java - 当我尝试添加外部 Jar 时转换为 dalvik 格式失败

c++ - 从 C++ 获取 shell 环境变量

c - 从 C 语言文件中读取 64 字节 block

c - 如何在 unix 中创建阻塞文件描述符?

android - 我如何知道用户是否已观看我的完整奖励视频广告或跳过 android 中的广告?

Android:在自定义适配器中调用了两次 getView()

android - 特定日期和时间的 AlarmManager

c++ - OpenGL 3.1 上下文创建后的 GL_INVALID_ENUM/GL_INVALID_OPERATION

c++ - 没有从 "const char"到 "int"的转换

c - 在 C 中将枚举映射到字符串的好方法