某天脑子中突然出现一个疑问:既然安卓系统是基于 Linux
开发的,那么安卓上的动态链接库能在 Linux
上调用吗?怀着这个疑问 Google
了一下。最终得到一个确定的的答案:
安卓动态链接库不可以在 GNU/Linux
发行版上直接使用。需要借助一个库 - libhybris
才能调用。
Android 与 Linux 区别
Android
系统内核虽然基于 Linux
,但二者使用的 C
标准库是不同的,GNU/Linux
使用的是 Glibc
,而安卓上则是 Bionic
(是谷歌专门为 Android
操作系统开发的)。两者并不完全兼容。因此基于 Bionic
编译的链接库不能直接运行在 Glibc
的系统上。
libhybris 出场
libhybris 主要作用就是为了解决 libc
库的兼容问题。它通过 Hook
的方式,将 Android
动态库对 Bionic
方法的引用,Link
到 Glibc
中对应的方法上,以实现 Android
动态库在 ARM Linux
上的支持。
编译 libhybris (基于安卓 9)
- 准备 1 台
ARM
架构的服务器,预装 Debian 11.5 64位 ARM 版
(可在阿里云购买:按量付费)
1.下载源代码
1 2 3 4 5 6 7 8 9 10 11 12 13
| $ apt install wget unzip
$ wget -O hybris.zip https://codeload.github.com/libhybris/libhybris/zip/refs/heads/master $ wget -O headers.zip https://codeload.github.com/droidian/android-headers-28/zip/refs/heads/droidian
$ unzip hybris.zip $ unzip headers.zip
$ mv ./android-headers-28-droidian /usr/include/android-headers
|
2.安装编译环境
1 2 3 4
| $ apt install make automake autoconf libtool pkg-config gawk
$ mkdir -p /var/task/libandroid
|
接下来将安卓 9 对应的链接库上传到 /var/task/libandroid
目录下。
- libc.so
- libm.so
- libstdc++.so
- libdl.so
- ld-android.so
3.执行编译
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| $ cd libhybris-master/hybris
$ ./autogen.sh --with-android-headers=/usr/include/android-headers --with-default-hybris-ld-library-path=/var/task/libandroid --prefix=/var/task/libhybris --enable-arch=arm64
$ make $ make install
$ export PATH=/var/task/libhybris/bin:$PATH $ export LD_LIBRARY_PATH=/var/task/libhybris/lib:$LD_LIBRARY_PATH $ export LIBRARY_PATH=/var/task/libhybris/lib:$LIBRARY_PATH
$ cp -r /var/task/libhybris/include /usr/
|
编译成功后会在 /var/task/
目录下生成 libhybris
目录,运行 test_dlopen
如果 libc.so
不为 nil
则表示安装成功
使用 nodejs 调用安卓库
1.编译 node-ffi
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| $ cd ~ $ wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash $ nvm install v18.19.0 $ nvm use v18.19.0
$ wget -O ffi.zip https://github.com/node-ffi-napi/node-ffi-napi/archive/refs/tags/v4.0.3.zip $ unzip ffi.zip
$ apt install binutils python3
$ cd node-ffi-napi-4.0.3
|
1 2 3 4 5 6 7 8 9 10 11
| # 修改源文件 src/ffi.h 第 17 行,添加一行: #include <hybris/common/dlfcn.h>
# 修改源文件 src/ffi.cc 第 43-46 行 o["dlopen"] = WrapPointer(env, hybris_dlopen); o["dlclose"] = WrapPointer(env, hybris_dlclose); o["dlsym"] = WrapPointer(env, hybris_dlsym); o["dlerror"] = WrapPointer(env, hybris_dlerror);
# 修改源文件 binding.gyp 第 13 行,添加一行: "libraries": ["-lhybris-common", "-landroid-properties"],
|
编译成功后会在项目目录下生成 build/Realease/ffi_bindings.node 文件
2.调用安卓库
1 2 3 4 5 6 7 8
| var ffi = require('./node-ffi-napi-4.0.3'); var libm = ffi.Library('libm', { 'ceil': ['double', ['double']] });
console.log(libm.ceil(1.5));
|
参考资料
Android应用的so,可以在Linux下使用吗?
Bionic 简介
Android bionic和GNU glibc
使用libhybris库linux调用android库
使用libhybris技术让linux调用android库
libhybris 编译和配置
Linux(ARM glibc)使用libhybris调用Android(ARM bionic)