djinni使用实践

djinni使用实践,第1张

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

cd `dirname 
#设置工程名
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} )`
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



`

rm -rf ../auto_gen/*

djinniFile(){
	java -jar ./djinni.jar \
	     --idl ../api_idl/\
	     \
	     --cpp-namespace test::hello \
	     --cpp-out ../auto_gen/cpp_impl/ \
	     --cpp-header-out ../auto_gen/public/include/ \
	     --hpp-ext h \
	     --ident-cpp-enum FOO_BAR \
	     --ident-cpp-method FooBar \
	     \
	     --java-out ../auto_gen/java// \
	     --java-package com.zhoumohan.djinni.gen \
	     --java-use-final-for-record true \
	     --jni-out ../auto_gen/jni/ \
	     --ident-jni-class JNIFooBar \
	     --ident-jni-file JNIFooBar \
	     --java-implement-android-os-parcelable false \
	     \
	     --objc-out ../auto_gen/objc/ \
	     --objcpp-out ../auto_gen/objc-cpp/ \
	     --objc-swift-bridging-header "test-hello-Bridging-Header"

}

//调用djinniFile这个函数,后面为两个参数,对应函数中的、变量
djinniFile info.djinni "common"

关于脚本文件如何编写,可以参考本系列的文章的第二篇。

执行generate.sh  shell脚本文件,没有报错的话,此时auto_gen文件夹及子文件已经成功生成了。

不难看出其中的对应关系。

然后我们来实现自动生成的c++接口,这样我们就能在java层调用c层的方法实现了。

test_djinni_wrapper.cpp

接下来第二步就是把生成的文件放到android工程里,进行混合编译,为了自动化编译我们也写了一个脚本来做文件的映射(软连接)。

build_android.sh

 

不过在执行此脚本之前配置你的sdk路径,及CMakeLists.txt的编写

CMakeLists.txt

 

大家可根据自己项目修改配置文件。

最后附上github地址,方便大家参考。djinniDemo

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/874792.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-13
下一篇 2022-05-13

发表评论

登录后才能评论

评论列表(0条)

保存