失效链接处理 |
Android java和C互相调用 PDF 下载
本站整理下载:
提取码:c5ij
相关截图:
主要内容:
一,CMakeLists
英文文档:https://cmake.org/documentation/
中文文档:https://www.zybuluo.com/khan-lau/note/254724
1,路径配置,在buildGradle的android层目中进行配置例如:
externalNativeBuild {
cmake {
path "src/main/cpp/CMakeLists.txt"
version "3.10.2"
}
}
path配置cmake的引用路径,version配置cmake的版本
2,添加库,在cmakeList中调用add_library函数
里面传入三个参数
第一个是要引入的库别名,第二个是库的类型,是静态库还是动态库。在Android中是不能引用静态库的也就是.dll后缀的库,所以第二个参数只要是引入第三方的.so库都是写“SHARED”,第三个是通过什么样方式引入进来,第三方的一般都是通过包含进来,所以第三个参数基本也是固定的都是写“IMPORTED”。
add_library后,就要设置.so的详细路径了,通过set_target_properties()函数来设置;该函数也是要传入三参数来指定.so库的路径。第一个参数和add_library的第一个参数一样,不过这里的库别名要和add_library的库别名要一致,要不然在编译时会报找不到库的错误。第二个参数是固定的,都是写“ PROPERTIES IMPORTED_LOCATION”主要用来指定库的引入方式。都是通过本地引入。第三个就是库的具体路径,这个不能写错,如果写错了,编译时也同样会找不到库的。只要是引入第三方的库使用add_library就要使用set_target_propeties这个组合,所以它们是成对出现的。
3,编译我们自己在项目中写的c/c++文件
调用方式和上面的add_library方法类似,前两个参数和上面传入的是一样的,最后一个参数写对应我们的c++的文件路径,可以写多个路径,如下:
add_library( # Sets the name of the library.
main-lib
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
main-lib.cpp
runoobtest.cpp)
这里就不用set_target_propeties()
4,下面一个函数是find_library
这个方法是用来寻找系统库的,如果有用用到系统库就要调用这个函数
第一个参数是库的别名,第二个参数表示该库在系统ndk中的名字如下:
# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.
find_library( # Sets the name of the path variable.
log-lib
# Specifies the name of the NDK library that
# you want CMake to locate.
log)
5,下一个方法是target_link_libraries,依赖的库
如果是系统的库要用这个格式${库的名字}。
如下:
# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.
target_link_libraries( # Specifies the target library.
native-lib
# Links the target library to the log library
# included in the NDK.
${log-lib})
target_link_libraries( # Specifies the target library.
main-lib
# Links the target library to the log library
# included in the NDK.
${log-lib}
)
二,java调用层C代码流程
第一种方式静态注册:
1,首先加载共享库,加载库一般是在在静态代码块中进行:
static {
System.loadLibrary("native-lib");
}
2,在Java中声明native方法
public native String stringFromJNI();
3,实现原生方法
#include <jni.h>
#include <string>
#include <android/log.h>
extern "C" JNIEXPORT jstring JNICALL
Java_com_test_jni_MainActivity_stringFromJNI(
JNIEnv *env,
jobject /* this */) {
std::string hello = "Hello from C++";
__android_log_print(ANDROID_LOG_ERROR,"TEST","HELLO ....... native lib");
return env->NewStringUTF(hello.c_str());
}
为了找到c代码中对应的方法,需要要Java关键字开头,在方法前面加上包名,并且以下划线隔开。上面的stringFromJjni声明在了com.test.jni这个包名的MainActivity里面。
这样在java代码里就可以调用stringFromJni这个方法了
第二种方式:动态注册
1,和静态注册一样,先加载共享库
static {
System.loadLibrary("dynamic-lib");
}
2,在java中声明native方法
public native int sum(int x, int y);
public native String getNativeString();
3,在c代码中中添加回调函数JNI_OnLoad方法,loadLibrary会执行该方法。
然后在JNI_OnLoad方法中调用方法RegisterNatives就完成注册了如下:
JNIEXPORT int JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
JNIEnv *env;
|