您当前的位置: 首页 > 慢生活 > 程序人生 网站首页程序人生
讓你的普通android Studio項目支持c++代碼的調用(向已有項目添加c的支持)
发布时间:2022-04-04 19:46:28编辑:雪饮阅读()
android Studio現在是支持c++代碼的調用,也就是ndk+jni實現。
cmake{
cppFlags ""
}
}
這第一個配置段是指定ndk的,這個我是參考那個新建c++支持的項目時候build過程中的日志信息中看到它用的ndk的版本信息,然後到安卓官網下載的我看到的這個版本信息所對應的ndk包,然後解壓后的路徑放置於這個ndkPath中。 那麽CMakeLists.txt建立好之後,接下來就是建立那個native-lib.cpp文件了。 用java調用c實現的函數 然後定義一個原生本地方法且沒有方法躰:
然後調用時如:
那麽包含這三個語句的局部代碼如:
}
externalNativeBuild {
cmake{
path "src/main/cpp/CMakeLists.txt"
}
}
path file ('src/main/cpp/CMakeLists.txt')
}
cmake_minimum_required(VERSION 3.4.1)
#add_library :建立共享库(把工程内的cpp文件都建立成共享库文件,方便经过头文件来调用,這裏所用的native-lib.cpp文件路徑是相對於當前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)
#find_library的用法
#首先是語法:
#find_library (
# <VAR>
# name | NAMES name1 [name2 ...] [NAMES_PER_DIR]
# [HINTS path1 [path2 ... ENV var]]
# [PATHS path1 [path2 ... ENV var]]
# [PATH_SUFFIXES suffix1 [suffix2 ...]]
# [DOC "cache documentation string"]
# [NO_DEFAULT_PATH]
# [NO_CMAKE_ENVIRONMENT_PATH]
# [NO_CMAKE_PATH]
# [NO_SYSTEM_ENVIRONMENT_PATH]
# [NO_CMAKE_SYSTEM_PATH]
# [CMAKE_FIND_ROOT_PATH_BOTH |
# ONLY_CMAKE_FIND_ROOT_PATH |
# NO_CMAKE_FIND_ROOT_PATH]
# )
#其實看起來這麽多,就是3個參數而已,第一個參數是變量,用來存儲通過find_library查找到庫的結果的(目前我理解為so庫)
#這第二個參數就是一要查找的庫名或多個可能的庫名
#這第三個參數就是從name這行下面的這些個帶有中括號的可選的參數列表中隨便選擇一個(可能也能使用多個吧)參數
#實例:FIND_LIBRARY(RUNTIME_LIB mylib /usr/lib /usr/local/lib NO_DEFAULT_PATH)
#對於這個實例,我的理解是從/usr/lib和/usr/local/lib中查找一個名為mylib的庫,查找到之後的結果存儲在runtime_lib這個變量上
#而如果沒有查到這個mylib庫的路徑,則查找結果將使用NO_DEFAULT_PATH賦值給runtime_lib
#那麽緊接著下面這個實際應用就是查找log這個庫的位置,並將查找到的結果存儲與log-lib變量中
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)
#將上面生成的(建立的)native-lib庫與這個新建的庫所要依賴的其它庫鏈接起來,這裏上面還查找到了log庫,而這裏新建的native-lib庫正好依賴log庫,log庫查找結果又正好在log-lib這個變量中
target_link_libraries( # Specifies the target library.
native-lib
# Links the target library to the log library
# included in the NDK.
${log-lib})
#include <string>
/*
extern "C":
extern直譯為外人。。。
作用:避免编绎器按照C++的方式去编绎C函数
1、C不支持函数的重载,编译之后函数名不变;
2、C++支持函数的重载(这点与Java一致),编译之后函数名会改变;
JNIEXPORT:
用来表示该函数是否可导出(即:方法的可见性)
通过查看 jni.h 中的源码,原来JNIEXPORT宏定义,像是這裏定義的是jni.h中定義如“#define JNIEXPORT __attribute__ ((visibility ("default")))”
attribute___((visibility ("default"))) 描述的是“可见性”属性 visibility
1、default :表示外部可见,类似于public修饰符 (即:可以被外部调用)
2、hidden :表示隐藏,类似于private修饰符 (即:只能被内部调用)
3、其他 :略
jstring:我可以理解為在c中實現的一個對應于java端的string類型
JNICALL:
同樣是一個宏定義在jin.h中,這裏是空定義“#define JNICALL”
所以這裏其實應該是可以不需要這個JNICALL的,有人測試這裏不用這個JNICALL也是可以的,但是據説
JNICALL的定义,并非所有平台都像Linux一样是空的,如windows平台:
#ifndef _JAVASOFT_JNI_MD_H_
#define _JAVASOFT_JNI_MD_H_
#define JNIEXPORT __declspec(dllexport)
#define JNIIMPORT __declspec(dllimport)
#define JNICALL __stdcall
typedef long jint;
typedef __int64 jlong;
typedef signed char jbyte;
#endif
不過windows平臺就有點扯遠了。。。
JNIEnv
JNIEnv 代表了Java环境,通过JNIEnv*就可以对Java端的代码进行操作,如:
├──创建Java对象
├──调用Java对象的方法
├──获取Java对象的属性等
jobject
jobject 代表了定义native函数的Java类 或 Java类的实例:
├── 如果native函数是static,则代表类Class对象
├── 如果native函数非static,则代表类的实例对象
函數名:
前面這些都是參數的一些配置,那麽函數名呢?
這裏我們是提供給咱們項目的包名:com.android.qs.video_push
那麽命名時候,是Java_前綴加上完整包名(一直到調用類的類名)再加上"_"再加上java端定義的native方法名,
包名路徑中的"."字符用"_"來代替,若包名中本來就包含有"_"則本來包含的"_"字符使用"_1"來代替
具體可見:https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/design.html#resolving_native_method_names
*/
extern "C" JNIEXPORT jstring JNICALL
Java_com_android_qs_video_1push_MainActivity_func1(
JNIEnv *env,
jobject /* this */) {
std::string hello = "Hello from C++";
//用java環境evn創建一個java端可以接收的字符串類型,接收的參數字符串是c兼容的char *类型即c_str()的返回
return env->NewStringUTF(hello.c_str());
}
System.loadLibrary("native-lib");
}
private Handler childHandler, mainHandler;
private CameraCaptureSession mCameraCaptureSession;
private ImageReader mImageReader;
private SurfaceView mSurfaceView;
private SurfaceHolder mSurfaceHolder;
private CameraDevice mCameraDevice;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toast.makeText(MainActivity.this, func1(), Toast.LENGTH_SHORT).show();
//SurfaceViewInit();
}
static {
System.loadLibrary("native-lib");
}
public native String func1();
关键字词:android,Studio,已有,c,c++