我正在尝试从 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>
}
关于android - 在另一个源文件中调用 JNI C 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53624310/