新建支持C/C++的工程¶
更新日期 2021-9-1
- 2021-9-1 更新格式
- 2020-5-28 创建文档
新建工程¶
新建支持C/C++的工程和我们创建工程的步骤基本一致。 在选择项目模板界面,选择Native C++卡片。
选择Native C++
点击下一步,然后填入项目的基本信息。
填入信息
然后一路点击下一步直至完成。
打开新建好的项目。可以看到cpp目录与java同级。 src/main/cpp中有 native-lib.cpp 和 CMakeLists.txt
另外一个值得关注的是gradle文件。里面有cmake
的配置。
报错: NDK not configured¶
若无报错请忽略本节
新建工程Build栏目出现报错信息
NDK not configured
NDK not configured. Download it with SDK manager. Preferred NDK version is '20.0.5594570'. Log: /SampleNDK/app/.cxx/ndk_locator_record.json
信息指出NDK工具没有配置好。ndk_locator_record.json
给出了详细的信息。
{
"level": "ERROR",
"message": "No version of NDK matched the requested version 20.0.5594570. Versions available locally: 18.1.5063045, 21.2.6472646"
}
项目要求NDK版本20.0.5594570,但电脑上没有与之匹配的版本。 我们前面安装的是21.2.6472646版本,可以在SDK Manager里下载安装NDK 20.0.5594570。 安装完毕后,重新打开这个项目即可。
运行工程¶
在手机上运行这个工程。可以看到效果。
运行效果
构建和运行过程大致如下:
- Gradle 调用您的外部构建脚本
CMakeLists.txt
。 - CMake 按照构建脚本中的命令将 C++ 源代码文件
native-lib.cpp
编译到共享的对象库中,并将其命名为libnative-lib.so
,Gradle 随后会将后者打包到 APK 中。 - 运行时,应用的
MainActivity
会使用System.loadLibrary()
加载原生库。现在,应用就可以使用库的原生函数stringFromJNI()
了。 MainActivity.onCreate()
会调用stringFromJNI()
,后者会返回“Hello from C++”
,并通过TextView
显示出来。
观察工程¶
首先关注cpp目录下的文件。
CMakeLists.txt¶
CMakeLists.txt是构建脚本。文件中进行一些配置。
add_library( # Sets the name of the library.
native-lib
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
native-lib.cpp )
target_link_libraries( # Specifies the target library.
native-lib
# Links the target library to the log library
# included in the NDK.
${log-lib} )
从文件中可以得知,库的名字叫做native-lib
,源文件是native-lib.cpp
。
以前可以用
Android.mk
来进行ndk-build。现在cmake取代了Android.mk
。
cpp文件¶
cpp文件是实现功能的地方。
#include <jni.h>
#include <string>
extern "C" JNIEXPORT jstring JNICALL
Java_com_rustfisher_samplendk_MainActivity_stringFromJNI(
JNIEnv* env,
jobject /* this */) {
std::string hello = "Hello from C++";
return env->NewStringUTF(hello.c_str());
}
注意方法的名字,Java_com_rustfisher_samplendk_MainActivity
是带有Java文件的包名。
stringFromJNI
是具体的方法名。
以前的ndk可以用
javah
生成.h
头文件。现在不需要自己手动生成了。
build.gradle¶
gradle中指定了CMake
的配置。
android {
defaultConfig {
externalNativeBuild {
cmake {
cppFlags ""
}
}
}
// ...
externalNativeBuild {
cmake {
path "src/main/cpp/CMakeLists.txt"
version "3.10.2"
}
}
}
Java文件¶
MainActivity
需要加载这个库。
定义关联的native方法。
.so 文件¶
刚才运行在armeabi-v7a架构的手机上。
编译生成的.so
文件在 app/build/intermediates/cmake/debug/obj/armeabi-v7a/libnative-lib.so
CMake 库文件命名规范:lib
+native-lib
+.so
。即 libnative-lib.so
生成release版apk时,会打包.so
文件进去。
修改工程¶
新建的工程中,配置和方法都是as默认的。我们可以根据自己的需要来修改。
修改库名¶
默认的库名字是native-lib
,可以自定义修改。
修改CMakeLists.txt。把库的名字改成fisher-lib
,cpp文件名字改成fisher-lib.cpp。
add_library( # Sets the name of the library.
fisher-lib
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
fisher-lib.cpp )
target_link_libraries( # Specifies the target library.
fisher-lib
# Links the target library to the log library
# included in the NDK.
${log-lib} )
cpp文件的名字改成fisher-lib.cpp。
MainActivity
文件中,修改库名。
再次编译运行即可。 可以在build目录中找到libfisher-lib.so。
添加native方法¶
仿照已有的方法,在MainActivity
中添加一个native方法。
fisher-lib.cpp文件中添加方法。注意要写上返回类型extern "C" JNIEXPORT int JNICALL
。
extern "C" JNIEXPORT int JNICALL
Java_com_rustfisher_samplendk_MainActivity_getIntFromJNI(
JNIEnv* env,
jobject /* this */) {
return 42;
}
编译运行即可。
本站说明
一起在知识的海洋里呛水吧。广告内容与本站无关。如果喜欢本站内容,欢迎投喂作者,谢谢支持服务器。如有疑问和建议,欢迎在下方评论~