Dart:ffi上手一:So库编译篇

我是首先去看了官方的前两个 example,都上手来跑了,然后对应理解每一部分,dart:ffi 的例子是在 pc 端,所以一系列的编译也是在 pc 端,可我是安卓端的 app,于是就遇见了第一个坑,交叉编译.c,.h 到 so 库

参考链接

https://www.kikt.top/posts/flutter/ffi/2-first-party/

Dart:ffi 官方文档

SO 库的编译

大致理清一下思路,.h 全是.c 文件的函数声明,还有结构体,宏的定义等等,单独的.c 语言编译后是可执行程序,打开就直接运行 main 函数,而 so 库(Android,Linux),dylib(Macos),dll(windows),是由.c,.h 共同编译的,这时候的.c 文件一般没有 main 函数,.h 复制提供函数声明但实际不参加编译过程,
我大致查了 so 库的编译,都说配置 Android.mk 比较麻烦我也就没有去了解了,整个编译的坑全靠上面第一个帖子趟过,我这自己走一遍

首先用 tree 命令查看目录结构,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$ tree -L 3 c-project
tree -L 3 c-project
c-project
├── android
│ ├── CMakeLists.txt
│ ├── build_android.sh
│ └── cmd
│ └── android.sh
├── ios
│ ├── CMakeLists.txt
│ ├── build_ios.sh
│ ├── cmd
│ │ └── ios_abi_build.sh
│ └── ios.toolchain.cmake
└── src
├── some.c
└── some.h

然后比着建立一个一样的目录结构(忽略图中无关的东西)

可以观察到有两个 sh 脚本,主脚本 build_android.sh,然后主脚本主要遍历出需要编译的架构,然后设置环境变量,调用副脚本 android.sh
src 里面就是.c 跟.h,我自己写的时候并没有写.h,也能出 so 库,所以我就没单独写了,可以观察到我脚本取消了.sh 的扩展名,这样就能直接通过 shebang 直接执行了,不会唤起我的 xcode,贴一下改过的两个脚本

build_android.sh

1
2
3
4
5
6
7
8
9
10
#!/bin/bash
cd /Users/nightmare/Desktop/C/nterm/android
rm -rf ./build
a="armeabi-v7a arm64-v8a x86 x86_64"
for abi in $a;
do
export ABI=$abi
sh cmd/android.sh
done
cp -rf ../../android/libs/* /Users/nightmare/Desktop/Flutter_Project/nightmare_tool/android/app/libs/

这串还是比较好懂得
cd 命令切换到了这个 C 项目的 android 目录下,export 即是更新一个环境变量,以让副脚本使用,我最后再用了 cp -rf 复制到了我的安卓项目的 libs 文件夹下,对应自己的路径改了就能用

android.sh

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#!/bin/bash
export NDK_HOME=/Users/nightmare/Library/Android/sdk/ndk/21.0.6113669 # or set to your ndk home

export MAKE_PATH=build/make-cache

export TARGET_ABI=$ABI

create_makefile() {
cmake \
-DANDROID_ABI=$TARGET_ABI \
-DANDROID_PLATFORM=android-16 \
-DCMAKE_BUILD_TYPE=release \
-DANDROID_NDK=$NDK_HOME \
-DCMAKE_TOOLCHAIN_FILE=$NDK_HOME/build/cmake/android.toolchain.cmake \
-DANDROID_TOOLCHAIN=clang -B $MAKE_PATH -S .
}

create_makefile

cd $MAKE_PATH

make clean
make

与上面链接的帖子中不一样的只有第一行,他的我不怎么能看懂,不过就是设置 NDK 所在的路径,NDK 需要用 Android Studio 的 SDK Manager 下载,在 FIle->Project Structure->Sdk Location 可以看到(这也是坑到我的一个地方)
CmakeLists.txt

1
2
3
4
5
6
7
8
9
cmake_minimum_required (VERSION 2.6) # cmake version

project(term) # project name

set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/../../android/libs/$ENV{ABI}) # set output path

aux_source_directory(${PROJECT_SOURCE_DIR}/../src SRC_FILES) # scan source code files

add_library(term SHARED ${SRC_FILES}) # add source code files to library, and set build type to dynamic library.

这些我对应改了自己的项目名称

运行如下


一般 c 语言没逻辑问题都能编译成功的,最后生成的文件在你项目同级文件夹下的 android 目录

OK 这篇就先结束了,都写在一起难理解

作者

梦魇兽

发布于

2020-02-22

更新于

2023-03-11

许可协议

评论