djinni使用实践(一) -- 官方文档
djinni使用实践(二) -- djinni究竟都有哪些配置选项
djinni使用实践(三)--Android项目中的使用
?????? 本篇是介绍djinni在Android项目中JNI开发的使用场景,所以默认大家有一定的Android JNI开发经验,此篇中涉及到的JNI相关的知识点不做介绍,大家可自行学习。
?????? djinni工具集成过程中需要用到该项目中的一些文件,我们先下载到本地以备使用
djinni项目地址
接下来先看下工程结构:
着重看下djinni相关的文件夹: api_generator
ok,工程整体结构大概就是这个样子,关于目录层级及目录名称大家可以按需调整。
???????? 接下来是构建整个项目中的第一个操作:根据djinni文件自动生成接口文件和bean文件,为了方便项目自动化构建我们将所有的要执行的命令行写成脚本文件。
info.djinni
//枚举
sex_mode_enum = enum {
SEX_MAN;
SEX_WOMAN;
}
//数据结构(java中的bean对象,c中的结构体)
test_info_store = record {
id: i32;
name: string;
project: string;
sex: sex_mode_enum;
}
//接口类
test_djnni_interface = interface +c {
show(testInfo: test_info_store): string;
static newInstance(): test_djnni_interface;
const version: i32 = 1;
}
djinni文件编写可参考本系列第一篇文章。
generate.sh
#!/bin/bash
#返回这个脚本文件放置的目录
cd `dirname $0`
rm -rf ../auto_gen/*
djinniFile(){
java -jar ./djinni.jar \
--idl ../api_idl/$1\
\
--cpp-namespace test::hello \
--cpp-out ../auto_gen/cpp_impl/ \
--cpp-header-out ../auto_gen/public/include/$2 \
--hpp-ext h \
--ident-cpp-enum FOO_BAR \
--ident-cpp-method FooBar \
\
--java-out ../auto_gen/java/$2/ \
--java-package com.zhoumohan.djinni.gen \
--java-use-final-for-record true \
--jni-out ../auto_gen/jni/$2 \
--ident-jni-class JNIFooBar \
--ident-jni-file JNIFooBar \
--java-implement-android-os-parcelable false \
\
--objc-out ../auto_gen/objc/$2 \
--objcpp-out ../auto_gen/objc-cpp/$2 \
--objc-swift-bridging-header "test-hello-Bridging-Header"
}
//调用djinniFile这个函数,后面为两个参数,对应函数中的$1、$2变量
djinniFile info.djinni "common"
关于脚本文件如何编写,可以参考本系列的文章的第二篇。
执行generate.sh? shell脚本文件,没有报错的话,此时auto_gen文件夹及子文件已经成功生成了。
不难看出其中的对应关系。
然后我们来实现自动生成的c++接口,这样我们就能在java层调用c层的方法实现了。
test_djinni_wrapper.cpp
接下来第二步就是把生成的文件放到android工程里,进行混合编译,为了自动化编译我们也写了一个脚本来做文件的映射(软连接)。
build_android.sh
#!/bin/bash
cd `dirname $0`
work_dir=$(pwd)
#配置ndk环境变量,将ndk的path赋值给ANDROID_NDK_ROOT
if [ $ANDROID_NDK_HOME ];then
ANDROID_NDK_ROOT=$ANDROID_NDK_HOME
fi
echo $ANDROID_NDK_ROOT
function clean(){
echo "clean"
rm -rf CMakeCache.txt
rm -rf CMakeFiles
rm -rf cmake_install.cmake
rm -rf Makefile
}
function unln_source_files {
echo "unln_source_files"
cd ..
base_path=$(pwd)
library_path=${base_path}/android_files/sample
dest_support="${library_path}/app/src/main/cpp/support_lib"
unlink ${dest_support}
dest_jni="${library_path}/app/src/main/cpp/jni"
for f in $(find $dest_jni -type l); do rm -rf $f; done
dest_header="${library_path}/app/src/main/cpp/header"
for f in $(find $dest_header -type l); do rm -rf $f; done
dest_src="${library_path}/app/src/main/cpp/common_src"
for f in $(find $dest_src -type l); do rm -rf $f; done
dest_java="${library_path}/app/src/main/java/com/zhoumohan/djinni/gen"
for f in $(find $dest_java -type l); do rm -rf $f; done
dest_third="${library_path}/app/src/main/cpp/third_part"
unlink ${dest_third}
}
function ln_source_files {
echo "ln_source_files"
base_path=$(pwd)
library_path=${base_path}/android_files/sample
# djinni库相关文件软链接
source_support="${base_path}/api_generator/support_lib"
dest_support="${library_path}/app/src/main/cpp/support_lib"
ln -snf $source_support $dest_support
# djinni生成的JNI接口文件的软链接
source_jni="${base_path}/api_generator/auto_gen/jni/common/*"
dest_jni="${library_path}/app/src/main/cpp/jni"
# djinni生成C++头文件的软链接
source_header="${base_path}/api_generator/auto_gen/public/include/common/*"
dest_header="${library_path}/app/src/main/cpp/header"
# 自己写的C++文件的软链接
source_src="${base_path}/src/common/*"
dest_src="${library_path}/app/src/main/cpp/common_src"
# 生成的java文件的软链接
source_java="${base_path}/api_generator/auto_gen/java/common/*"
dest_java="${library_path}/app/src/main/java/com/zhoumohan/djinni/gen"
# 第三方库(c++)的软链接
source_third="${base_path}/third_part"
dest_third="${library_path}/app/src/main/cpp/third_part"
ln -snf $source_third $dest_third
mkdir -p $dest_jni
mkdir -p $dest_header
mkdir -p $dest_src
mkdir -p $dest_java
ln -snf $source_jni $dest_jni
ln -snf $source_header $dest_header
ln -snf $source_src $dest_src
ln -snf $source_java $dest_java
}
function build_android() {
echo "build_android"
pwd
cd "android_files/sample/app/src/main/cpp"
cmake . \
-DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK_ROOT/build/cmake/android.toolchain.cmake \
-DCMAKE_SYSTEM_NAME=Android \
-DANDROID_NDK=$ANDROID_NDK_ROOT \
-DANDROID_ARM_NEON=ON \
-DANDROID_PLATFORM=android-14 \
-DANDROID_STL=c++_shared \
-DANDROID_TOOLCHAIN=clang \
-DCMAKE_BUILD_TYPE=Release \
-DANDROID_ABI=armeabi-v7a
make -j4
clean
}
unln_source_files
ln_source_files
build_android
cd $work_dir
不过在执行此脚本之前配置你的sdk路径,及CMakeLists.txt的编写
CMakeLists.txt
#设置工程名
project("mytest")
#设置最低版本
cmake_minimum_required(VERSION 3.6.0)
#给变量赋值,设置编译参数,指定c++标椎库
#set(CMAKE_C_FLAGS_RELEASE "-std=c++11 -O2 -s ")
set(CMAKE_CXX_FLAGS_RELEASE "-std=c++11 -O2 ")
#set(CMAKE_C_FLAGS_DEBUG "-std=c++11 -O2 ")
set(CMAKE_CXX_FLAGS_DEBUG "-std=c++11 -O2 ")
set(COMMON_SRC_ROOT "./common_src/")
#加载以下路径中的所有文件
file(GLOB all_src
"${COMMON_SRC_ROOT}/*.hpp"
"${COMMON_SRC_ROOT}/*.cpp"
)
#构建一个库供他人使用(库名称(name) 库类型 源文件),
#用于指定从一组源文件 source1 source2 … sourceN 编译出一个库文件且命名为 name
add_library(mytest SHARED
${all_src})
file(GLOB jni_src
"${CMAKE_CURRENT_SOURCE_DIR}/jni/*.h"
"${CMAKE_CURRENT_SOURCE_DIR}/jni/*.cpp"
)
#向test库添加源文件
target_sources(mytest PRIVATE ${jni_src})
#添加头文件
target_include_directories(mytest PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/header
)
#添加头文件
target_include_directories(mytest PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/support_lib/include/jni
${CMAKE_CURRENT_SOURCE_DIR}/support_lib/include
)
file(GLOB support_src
"${CMAKE_CURRENT_SOURCE_DIR}/support_lib/*.cpp"
)
target_sources(mytest PRIVATE ${support_src})
set(PROJECT_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../..)
if (${CMAKE_BUILD_TYPE} STREQUAL "Release")
set_target_properties(mytest
PROPERTIES
ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_ROOT}/android_files/android_out/${CMAKE_ANDROID_ARCH_ABI}"
LIBRARY_OUTPUT_DIRECTORY "${PROJECT_ROOT}/android_files/android_out/${CMAKE_ANDROID_ARCH_ABI}")
elseif (${CMAKE_BUILD_TYPE} STREQUAL "Debug")
set_target_properties(mytest
PROPERTIES
ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_ROOT}/android_files/android_out/${CMAKE_ANDROID_ARCH_ABI}/Debug"
LIBRARY_OUTPUT_DIRECTORY "${PROJECT_ROOT}/android_files/android_out/${CMAKE_ANDROID_ARCH_ABI}/Debug")
endif()
find_library( log-lib
log )
target_link_libraries( mytest
${log-lib} )
大家可根据自己项目修改配置文件。
最后附上github地址,方便大家参考。djinniDemo
|