我是首先去看了官方的前两个example,都上手来跑了,然后对应理解每一部分,dart:ffi的例子是在pc端,所以一系列的编译也是在pc端,可我是安卓端的app,于是就遇见了第一个坑,交叉编译.c,.h到so库
参考链接
https://www.kikt.top/posts/flutter/ffi/2-first-party/
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
然后比着建立一个一样的目录结构(忽略图中无关的东西)
可以观察到有两个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这篇就先结束了,都写在一起难理解
网友评论