前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >SQLite在NDK中的重生

SQLite在NDK中的重生

作者头像
用户1907613
发布2018-07-20 15:09:37
1.4K0
发布2018-07-20 15:09:37
举报
文章被收录于专栏:Android群英传Android群英传

这个问题的起因是,某项目需要在 NDK 中使用 SQLite,并且这个库同时也需要在 iOS 端使用。一开始的开发均很顺利,已有文章予以总结,点击查看该文章(http://rarnu.com/index.php/2017/03/17/sqlite_cross_platform/)。

但是当程序运行到 Android N 上时,情况就不对了,整个程序直接崩溃,报的错误是 Can not load dynamic library "libsqlite.so"。保险起见,我检查了一下 /system/lib/system/lib64,确保了 libsqlite.so 是存在的。那么问题就变成了,无法调用这个存在的库?

经过一番搜索,找到了问题的原因,点此查看原文(http://ericsink.com/entries/sqlite_android_n.html),具体的原因是,Android N 以后,不再允许直接调用 /system/lib 内的内容,而允许调用的库,如 liblog.so,均被移至 vendor 下,并符号链接至 /system/lib

所以,libsqlite.so 既便存在,也无法再直接调用了。再深入讲一句,其实 libdl.so 也无法再使用了,也就是说,在 NDK 中 dlopendlsym 这类函数也已被禁用。


既然不能动态调用,那解决方案就是静态调用了,我们需要一个 libsqlite.a,并把它静态链接到目标库里。这一步很简单,下载 SQLite 源码后,将它编译成适用于 Android 的 libsqlite.a

此时可以得到 SQLite 的源码,总共 4 个文件,写一个 Android.mk 来编译之:

同时还需要再写一个 Application.mk 来使用 STL:

执行一下 ndk-build 命令即可得到一个 libsqlite3.a


要完成静态链接,可以很简单的使用 linklib 这个宏命令,同时修改 sqlite3.inc 文件,将 external 指令后的库名称全部删去。

关于 external,详细的用法是:

关于 linklib,详细的用法是:

此处需要注意的是,我们仅针对 Andorid 平台进行入理,而其他平台上静态链接并没有意义,因此使用 Android 的定义宏将 linklib 包起来即可。这样在编译时,静态库就链接到目标文件里去了。


到了这一步,可以说是成功了一半,这个时候运行程序,还是会崩的,主要会崩的地方有以下几个:

这两个函数的调用,须注释掉,在这里并不需要使用,而且放着会引起找不到函数的运行时异常。

另一处崩溃在于 Android 老版本的兼容,在 Android M 以后,调用 NDK 时,不再检查 __aeabi_d2ulz__aeabi_d2lz(虽然这两个函数具体做了什么我也不知道,但是反编译看函数体,是可以直接留空的),而老版本的 Android 会在调用 NDK 时进行导出函数检查,从而引发一个崩溃。要解决这个问题,只需要造出这两个函数即可:

这样就完成了对老版本 Android 的兼容。到了这一步,在 Android N 以上以 NDK 调用 SQLite 即告完成。

会!

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2017-03-31,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 群英传 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档