工作需要,从三方获取到一个 so 和头文件 (头文件里的函数不是 JNI 标准头)
写一个工具类封装好 native 方法,再写一个 cpp 文件定义好 JNI 标准头
CMakeLists 文件里定义好 SHARED 的 native 和 IMPORTED 的三方库
在 cpp 文件里 import 头文件,然后直接调用头文件中定义好的函数
前面都没有问题
结果 build 失败了,显示在 cpp 中调用的函数都不存在
想了想 我写了一个 cpp 类文件,打包出一个 so 文件 是可以正常使用的
但是使用 cpp 文件 直接定义函数 然后打包出一个 so 文件 就无法正常使用了- - (已经都用 extern "C"包裹了)
我问了下三方的开发 他们果然是使用 cpp 后缀 但是直接定义的函数
不知道大家在做 JNI 的过程中有没有遇到这样的情况,是如何解决的?
谢谢大家:)
1
lrannn 2017-09-19 18:05:40 +08:00
是不是 CMakeLists 中没有链接好第三方动态库?
|
2
BigUncleLee OP |
3
wshcdr 2017-09-19 18:24:49 +08:00
关注下这个问题...
|
4
xhcnb 2017-09-19 18:40:47 +08:00
查看出错的信息, 找不到的符号名称是什么, 再用 ndk 下面的 readelf 或 nm 查看 so 里的符号表, 对比一下
C 和 C++生成的函数符号是不一样的, 确保编译时头文件和源文件都被正确的处理, 比如 cpp 里函数使用 extern "C", 那么头文件里的声明也必须是 extern "C" 描述的可能不太清楚, 看一下生成的 so 符号表和报错的信息一下子就明白了 |
5
TonyHoAspire 2017-09-19 18:42:51 +08:00 1
如果你对 ELF 以及编译链接的过程非常熟悉的话可以这样子做:
0. gcc 手动 compile 与 link,得到 verbose 信息。确定 link 的时候确实用到了 so 文件( input object ),如果 link 确实将 so 文件作为了 input,那么看下面的 1,否则设置好-L -l 选项 1. 用 IDA Pro,或者 binutils 工具( readelf,objdump )来查看 so 文件中的 symbols,看看 undefined 的 symbols 在 ELF 文件(你这里是.so 文件)中的的 names 属性( export 的 Global ?还是确实 undefined ),如果确实 undefined 的话那么就是 so 的问题了。但是这种情况少见。 2. 如果是 names 的问题,那么用 c++-filt 来解析确定原本的 symbol 名字是正确的,将头文件改正确即可,当然你也可以修改 so 文件来完成。 最后如果是 arm instruction 的话,可能需要注意 CPU 与指令集甚至 fpu 的 tuning 选项。 |
6
RLib 2017-09-20 08:29:04 +08:00
你明白 extern "C" 的作用吗?可能是这里的问题
|