语言有的时候表述一件事真的很乏力,可能我理解的并没有完全清楚的表达出来,如果你看到了,并且理解不了,那么,就多琢磨吧
1、CMakeLists.txt篇(注意,这个文件的内容识别不区分大小写的):
1)设置输出.so文件目录设置:
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/../outputJniLibs/${ANDROID_ABI})
说明:
PROJECT_SOURCE_DIR指的是当前CMakeLists.txt文件所在目录,
/..是上一级目录的意思,
ANDROID_ABI是指在app.build文件android -》defaultConfig -》externalNativeBuild -》cmake 下的abiFilters定义的一组目录
举个栗子:
如果当前CMakeLists.txt文件在app文件夹下,并且,那么abiFilters值为"x86","x86_64",那么上面的设置就会把生 成的.so文件放在本项目的 顶级目录 文件夹下的outputJniLibs中的x86文件夹和x86_64文件夹,不过实验结果好像是, 运行到什么架构的手机上就会在相应架构的文件夹下生成.so库,其他的文件夹倒不会生成,不知原因为何
2)只生成一个.so文件的设置:
(1)设置生成库的源代码:
add_library(NativeHelper SHARED src/main/cpp/one/com_liuchaoya_c_NativeHelper.cpp)
说明:这个方法有三个参数,分别以空格分割。
NativeHelper 要生成的.so库的名称,
SHARED 是否作为共享库,这个一般不用动,我是不会动,
src/main/cpp/one/com_liuchaoya_c_NativeHelper.cpp 生成库所需要的源文件
(2)设置要链接的目标库:target_link_libraries(NativeHelper ${log-lib}).
说明:这个方法有两个参数,分别以空格分割。
NativeHelper 需要链接的目标库,
${log-lib} 要链接的目标库,这个log-lib库是在NDK中定义好了的,直接链上,毫不犹豫
3)生成多个.so文件的设置:
(1)直接添加如下代码(测试只生成两个库)
ADD_SUBDIRECTORY(src/main/cpp/one)
ADD_SUBDIRECTORY(src/main/cpp/two)
对这里的参数 路径进行一下解释:
前提:这里测试的源码分别在app下的src/main/cpp/one和src/main/cpp/two文件夹中。
说明:这个路径仍然是跟着CMakeLists.txt文件的位置走的,当CMakeLists.txt文件在app下时,
这个路径就是src/main/cpp/*, *代表目录名,
当CMakeLists.txt在app的src/main/cpp下时,则可以直接这样写
ADD_SUBDIRECTORY(one)
ADD_SUBDIRECTORY(two)
就不用要前面的src/main/cpp/了
(2)设置子目录src/main/cpp/one和src/main/cpp/two下的CMakeLists.txt文件:
src/main/cpp/one下:
add_library(NativeHelper SHARED com_liuchaoya_c_NativeHelper.cpp)
target_link_libraries(NativeHelper log)
参数意义已经在上面的2)和3)中讲过
src/main/cpp/two下:
add_library(NativeCHelper SHARED com_liuchaoya_c_NativeCHelper.c)
target_link_libraries(NativeCHelper log)
以上两个文件内容的区别就是指定了库的名称和源文件路径,仅此而已。
2、java调用工具类:
1)不要忘了加载库
static {
System.loadLibrary("库名称");
}
2)方法最好是静态,方便调用
3、cpp源码:
1)需要将方法包括在
extern "C"{...} 中,不然调用不到,会报没有对应实现了的方法的错误
2)方法名遵循 以下规则:Java_包名_工具类名_方法名
例如:Java_com_liuchaoya_c_NativeHelper_getNativeString,这里
com_liuchaoya_c是包名(要加上工具类所在各级目录名),
NativeHelper是工具类名,
getNativeString是方法名,
3)返回值用法:
以返回一个字符串为例:
cpp代码 中是 return env->NewStringUTF("字符串");
c代码 中是 return (*env)->NewStringUTF(env, "字符串");
注意区别
4、c源码:
1)不需要将方法包括在
extern "C"{...} 中,直接写方法就行
extern "C"的意思就是将包括的代码以C语言进行处理编译,而本身就是c的话就无需转换
2)其他同cpp基本相同,唯一一点返回值的区别在cpp中已经说过