在另一个源文件中调用 JNI C 函数
Calling JNI C function in another source file
我正在尝试从 JNI 本机 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 会通知我 "This file is not part of the project. Please include it in the appropriate build file (build.gradle, CMakeLists.txt or Android.mk etc.) and sync the project." 我该怎么做?
可能的问题是您的 foo()
函数被 linker 识别为 C++
函数,而不是 C
函数。
由于 C++
函数可以被重载,C++ 编译器 "mangles" 这个名字使得 linker 有一个函数的唯一键。任何遇到 foo.h
的 C++ 模块都将假定该函数是 C++ 函数,因此将对函数名进行名称重整。
例如,在编译后的 object 代码中,经过修饰的名称可能看起来像这样:
foo@ucharp@uintp@int
(每个品牌的 C++ 编译器都有自己的命名方案)。
另一方面,当 C
编译器遇到 foo.h
时,编译后的 object 代码生成一个代表 "unmangled" foo
名称的符号,或多或少,这个:
foo
或 _foo
所以现在在 link 时间,因为你从 C++ 代码调用了 foo
函数,linker 将尝试找到损坏的版本,因为没有 C++名为 foo
的函数,您会收到 linker 错误。
所以基本上你的 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>
}
我正在尝试从 JNI 本机 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 会通知我 "This file is not part of the project. Please include it in the appropriate build file (build.gradle, CMakeLists.txt or Android.mk etc.) and sync the project." 我该怎么做?
可能的问题是您的 foo()
函数被 linker 识别为 C++
函数,而不是 C
函数。
由于 C++
函数可以被重载,C++ 编译器 "mangles" 这个名字使得 linker 有一个函数的唯一键。任何遇到 foo.h
的 C++ 模块都将假定该函数是 C++ 函数,因此将对函数名进行名称重整。
例如,在编译后的 object 代码中,经过修饰的名称可能看起来像这样:
foo@ucharp@uintp@int
(每个品牌的 C++ 编译器都有自己的命名方案)。
另一方面,当 C
编译器遇到 foo.h
时,编译后的 object 代码生成一个代表 "unmangled" foo
名称的符号,或多或少,这个:
foo
或 _foo
所以现在在 link 时间,因为你从 C++ 代码调用了 foo
函数,linker 将尝试找到损坏的版本,因为没有 C++名为 foo
的函数,您会收到 linker 错误。
所以基本上你的 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>
}