请教关于 android JNI 方法 undefined reference 问题

2017-09-19 17:39:57 +08:00
 BigUncleLee

工作需要,从三方获取到一个 so 和头文件 (头文件里的函数不是 JNI 标准头)
写一个工具类封装好 native 方法,再写一个 cpp 文件定义好 JNI 标准头
CMakeLists 文件里定义好 SHARED 的 native 和 IMPORTED 的三方库
在 cpp 文件里 import 头文件,然后直接调用头文件中定义好的函数
前面都没有问题
结果 build 失败了,显示在 cpp 中调用的函数都不存在

想了想 我写了一个 cpp 类文件,打包出一个 so 文件 是可以正常使用的
但是使用 cpp 文件 直接定义函数 然后打包出一个 so 文件 就无法正常使用了- - (已经都用 extern "C"包裹了)
我问了下三方的开发 他们果然是使用 cpp 后缀 但是直接定义的函数

不知道大家在做 JNI 的过程中有没有遇到这样的情况,是如何解决的?
谢谢大家:)

4678 次点击
所在节点    Android
6 条回复
lrannn
2017-09-19 18:05:40 +08:00
是不是 CMakeLists 中没有链接好第三方动态库?
BigUncleLee
2017-09-19 18:10:30 +08:00
@lrannn 链接是没问题的
诡异的时 我使用 cpp 定义类的方式打出的 so 是可以找到函数的
用 cpp 定义函数的方式打出 so 其它都不做更改 就找不到了- -
wshcdr
2017-09-19 18:24:49 +08:00
关注下这个问题...
xhcnb
2017-09-19 18:40:47 +08:00
查看出错的信息, 找不到的符号名称是什么, 再用 ndk 下面的 readelf 或 nm 查看 so 里的符号表, 对比一下
C 和 C++生成的函数符号是不一样的, 确保编译时头文件和源文件都被正确的处理, 比如 cpp 里函数使用 extern "C", 那么头文件里的声明也必须是 extern "C"
描述的可能不太清楚, 看一下生成的 so 符号表和报错的信息一下子就明白了
TonyHoAspire
2017-09-19 18:42:51 +08:00
如果你对 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 选项。
RLib
2017-09-20 08:29:04 +08:00
你明白 extern "C" 的作用吗?可能是这里的问题

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/392017

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX