Dart FFi 探索(一)| So库编译篇

4,803 阅读1分钟

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

参考链接

www.kikt.top/posts/flutt…

Dart:ffi官方文档

SO库的编译

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

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

$ 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

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

build_android.sh

#!/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

#!/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

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.

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

运行如下

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

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