AndroidStudioNDK开发案例⼆JNI包含多个cpp⽂件
上⼀章节我们学会了如何使⽤Android Studio开发JNI,但是上⼀章节针对的是单个cpp⽂件,我们做项⽬开发时肯定不⽌⼀个cpp⽂件,假如这些cpp⽂件能够放在⼀个单独的⽂件夹下⾯肯定会更⽅便我们的操作,但是这些该如何实现呢?其实我们只需要修改及重新定向的路径就可以实现。
1、在cpp⽬录下创建⽂件夹helloworld,将native-lib.cpp移动到helloworld⽂件夹,并在helloworld⽂件夹下创建.cpp和.h⽂件,结构如下:
./cpp/helloworld
|
+--- native-lib.cpp
|
+--- helloworld.cpp
|
+--- helloworld.h
|
+--- includes.h
cmake如何使用|
源码如下:
#include <jni.h>
#include <string>
#include "includes.h"
extern "C"
JNIEXPORT jstring JNICALL
Java_com_example_administrator_myapplication_MainActivity_stringFromJNI(        JNIEnv* env,
jobject /* this */) {
std::string hello = "Hello from C++";
return env->NewStringUTF(hello.c_str());
}
extern "C"
JNIEXPORT jstring JNICALL
Java_com_example_administrator_myapplication_MainActivity_helloworldJNI(        JNIEnv* env,
jobject instance) {
std::string hello = helloworld();
return env->NewStringUTF(hello.c_str());
}
//helloworld.cpp
//
// Created by taxiangxuezi on 2018/12/6 0006.
//
#include "includes.h"
/*******************************************************************************
* 函数名称: char * helloworld(void)
* 函数功能:
* 输⼊参数:
* 输出参数:
* 返回值  :
*******************************************************************************/
char * helloworld(void)
{
char *ptr = "hello world";
return ptr;
}
//
// Created by taxiangxuezi on 2018/12/6 0006.
//
#ifndef MYAPPLICATION_HELLOWORLD_H
#define MYAPPLICATION_HELLOWORLD_H
extern char * helloworld(void);
#endif //MYAPPLICATION_HELLOWORLD_H
//includes.h
//
/
/ Created by taxiangxuezi on 2018/12/6 0006.
//
#ifndef MYAPPLICATION_INCLUDES_H
#define MYAPPLICATION_INCLUDES_H
#include "helloworld.h"
#endif //MYAPPLICATION_INCLUDES_H
这样将所有源码放在⼀个⽂件夹,⽅便管理和移植。
2、源⽂件准备好后,开始修改编译链接规则。我们知道在创建JNI⼯程时,在app/⽬录下会⾃动⽣成,如下图:
此处为了今后使⽤⽅便,我们使⽤⾃⼰⽣成的,重新⽣成的位置结构如下:
|      |
|      +--- native-lib.cpp
|      |
|      +--- helloworld.cpp
|      |
|      +--- helloworld.h
|      |
|      +--- includes.h
|      |
|      +---
|      |
|
|
+---
|
两个的源码如下:
// ./
#指定需要CMAKE的最⼩版本
cmake_minimum_required(VERSION 3.4.1)
#C的编译选项是 CMAKE_C_FLAGS
#指定编译参数,可选
SET(CMAKE_CXX_FLAGS "-Wno-error=format-security -Wno-error=pointer-sign")
#设置⽣成的so动态库最后输出的路径
#set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/../jniLibs/${ANDROID_ABI})
#设置头⽂件搜索路径(和此txt同个路径的头⽂件⽆需设置),可选
#INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/common)
#指定⽤到的系统库或者NDK库或者第三⽅库的搜索路径,可选。
#LINK_DIRECTORIES(/usr/local/lib)
#添加⼦⽬录,将会调⽤⼦⽬录中的
ADD_SUBDIRECTORY(helloworld)
// ./cpp/
#⽣成so动态库
# 查当前⽬录下的所有源⽂件,并保存到 DIR_LIB_SRCS 变量
aux_source_directory(. DIR_LIB_SRCS)
# ⽣成链接库
ADD_LIBRARY(native-lib SHARED ${DIR_LIB_SRCS})
# 导⼊当前⽬录下的所有头⽂件
include_directories(.)
find_library(log-lib log)
target_link_libraries(native-lib ${log-lib})
aux_source_directory 查在某个路径下的所有源⽂件。
aux_source_directory(< dir > < variable >)
  搜集所有在指定路径下的源⽂件的⽂件名,将输出结果列表储存在指定的变量中。该命令主要⽤在那些使⽤显式模板实例化的⼯程上。模板实例化⽂件可以存储在Templates⼦⽬录下,然后可以使⽤这条命令⾃动收集起来;这样可以避免⼿⼯罗列所有的实例。
  使⽤该命令来避免为⼀个库或可执⾏⽬标写源⽂件的清单,是⾮常具有吸引⼒的。但是如果该命令貌似可以发挥作⽤,那么CMake就不需要⽣成⼀个感知新的源⽂件何时被加进来的构建系统了(也就是说,新⽂件的加⼊,并不会导致过时,从⽽不能引起CMake重新运⾏。——译注)。正常情况下,⽣成的构建系统能够感知它何时需要重新运⾏CMake,因为需要修改来引⼊⼀个新的源⽂件。当源⽂件仅仅是加到了该路径下,但是没有修改这个⽂件,使⽤者只能⼿动重新运⾏CMake来产⽣⼀个包含这个新⽂件的构建系统。
打开\MyApplication\adle,修改路径,源码如下:
externalNativeBuild {
cmake {
path "src/main/"
}
}

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。