問題的引入
創(chuàng)建了一個(gè) Android Studio 工程,在實(shí)現(xiàn)了許多功能后,需要在當(dāng)前的工程中調(diào)用一些 C++ 代碼,在網(wǎng)上查了一些資料,發(fā)現(xiàn),都是在創(chuàng)建 Android Studio 工程時(shí),就加入 C++ 支持,我不想重新創(chuàng)建帶 C++ 支持的 Android Studio 工程,因?yàn)橛行┕ぷ餍枰谛鹿こ讨兄貜?fù)做,很麻煩,于是,就想直接在當(dāng)前 Android Studio 工程添加 C++ 代碼。
實(shí)現(xiàn)方法簡述
我采用的這種方法:創(chuàng)建了一個(gè) Android Studio 工程,選用 “Empty Activity”,再創(chuàng)建了一個(gè) Android Studio 工程,選用 “Native C++” ,然后對比了兩個(gè)工程的文件差異,從這些差異中,找到了方法。
具體步驟
下面詳述添加方法。我的環(huán)境是:win10,Android Studio 版本如下:
假設(shè)已經(jīng)有了一個(gè) Android Studio 工程(我這里是 javatest2),在創(chuàng)建它時(shí),并不是 “Native C++”,現(xiàn)在需要在其中加入 “C++” 代碼。
1 創(chuàng)建 cpp 文件夾
在 app/src/main 文件夾下(如下圖所示),創(chuàng)建 cpp 文件夾,當(dāng)然也可以是其他名字,比如 cxx,這個(gè)可以隨意。
創(chuàng)建好后如下圖所示:
2 在 cpp 文件夾下創(chuàng)建其他文件
在 cpp 中創(chuàng)建 inc 和 src 文件夾,以及 CMakeLists.txt,inc 用于存放 C++ 頭文件,src 用于存放 C++ 源文件,這兩個(gè)文件夾也不是必須的,只是我喜歡這樣分類存放,CMakeLists.txt 是必須的,它用于指示如何編譯 C++ 源文件。創(chuàng)建好后,如下圖所示:
3 創(chuàng)建 C++ 源文件
在 inc 文件夾中,放入你的 C++ 頭文件(我這里是 CalMinMax.h),在 src 文件夾中,放入你的 C++ 源文件(我這里是 CalMinMax.cpp),在 cpp 文件夾中,創(chuàng)建一個(gè)源文件(我這里是 native-lib.cpp)。如下圖所示:
4 編寫源代碼
CalMinMax.h 代碼:
#ifndef JAVACPP_CALMINMAX_H
#define JAVACPP_CALMINMAX_H
#include <string>
std::string calMinMax(int a, int b);
#endif //JAVACPP_CALMINMAX_H
CalMinMax.cpp 代碼:
#include "CalMinMax.h"
std::string calMinMax(int a, int b)
{
if (a > b)
return std::string("Max string");
else
return std::string("Min string");
}
native-lib.cpp 代碼,這里面定義了一些 JNICALL,它會直接調(diào)用到 C++ 代碼(在這里,它調(diào)用了 calMinMax),要根據(jù)你的實(shí)際情況修改。
Java_com_example_javatest2_MainActivity_stringFromJNI 中,com_example_javatest2 跟包名相同(“.” 用 “_” 代替了),MainActivity 是要調(diào)用的 java 文件,stringFromJNI 是真正的方法名,注意名字不能有錯誤,不然在運(yùn)行時(shí)會出錯。
#include <jni.h>
#include <string>
#include "CalMinMax.h"
extern "C" JNIEXPORT jstring JNICALL
Java_com_example_javatest2_MainActivity_stringFromJNI(
JNIEnv* env,
jobject /* this */,
jint a,
jint b) {
std::string hello = calMinMax(a, b);
return env->NewStringUTF(hello.c_str());
}
CMakeLists.txt 代碼,注意,如果你創(chuàng)建的文件夾或者文件名不同,要做相應(yīng)的修改,有些路徑也要相應(yīng)地修改。
# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html
# Sets the minimum version of CMake required to build the native library.
cmake_minimum_required(VERSION 3.10.2)
# Declares and names the project.
project("javacpp")
# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.
add_library( # Sets the name of the library.
javacpp
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
native-lib.cpp
src/CalMinMax.cpp)
include_directories(inc/)
# 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)
# 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.
javacpp
# Links the target library to the log library
# included in the NDK.
${log-lib})
說明一下,上面的 CMakeLists.txt 代碼 與 native-lib.cpp 代碼,用了 Android Studio 工程(選擇 “Native C++” 時(shí))自動生成的代碼,但是做了一點(diǎn)修改。
5 在 java 文件中調(diào)用 C++ 代碼
我這里示例,在 MainActivity.java 中調(diào)用,如下圖所示:
注意,在調(diào)用 System.loadLibrary 時(shí),libname 要與 CMakeLists.txt 中的 name of the library 相同。下面的 “public native String stringFromJNI(int a, int b);” 就是在聲明方法。
6 修改 gradle 文件
修改下面的 gradle 文件:
修改如下,共有兩處:
注意,ndkVersion 與你自己 Android Studio 中安裝的 ndk 保持一致。
7 運(yùn)行測試
運(yùn)行結(jié)果如下:
8 其他說明
上面只是一個(gè)示例,有些地方寫得不夠規(guī)范,更好的做法是,將要調(diào)用 C/C++ 函數(shù)的 native 方法,全部寫到一個(gè) java 類中,統(tǒng)一管理。比如,上面的示例中,可以新建一個(gè) java 類 MyC_CppFunc,將 native 聲明放到這個(gè)類中,如下所示:
// 這里放你的包名
package com.example.javatest2;
public class MyC_CppFunc {
// Used to load the 'javacpp' library on application startup.
static {
System.loadLibrary("javacpp");
}
/**
* A native method that is implemented by the 'javacpp' native library,
* which is packaged with this application.
*/
public native String stringFromJNI(int a, int b);
}
這時(shí),native-lib.cpp 代碼要做一些修改,主要是 JNICALL 的名字,因?yàn)橹苯诱{(diào)用 C/C++ 函數(shù)的 java 類發(fā)生了變化,所以,名字要改為:Java_com_example_javatest2_MyC_1CppFunc_stringFromJNI,這里有一個(gè)小細(xì)節(jié),前面的名字中,是 MyC_1CppFunc 而不是 MyC_CppFunc,下劃線后面多了一個(gè) “1”,因?yàn)榘械?“.” 用下劃線代替了,而 java 類名中有一個(gè) 下劃線,如果不做特殊處理,會解析出錯,所以規(guī)定要在 下劃線后面加上 “1”。文章來源:http://www.zghlxwxcb.cn/news/detail-841463.html
#include <jni.h>
#include <string>
#include "CalMinMax.h"
extern "C" JNIEXPORT jstring JNICALL
Java_com_example_javatest2_MyC_1CppFunc_stringFromJNI(
JNIEnv* env,
jobject /* this */,
jint a,
jint b) {
std::string hello = calMinMax(a, b);
return env->NewStringUTF(hello.c_str());
}
如果要在 MainActivity.java 中調(diào)用,可以這樣做,先創(chuàng)建 MyC_CppFunc 類的對象,然后用它的對象調(diào)用:文章來源地址http://www.zghlxwxcb.cn/news/detail-841463.html
MyC_CppFunc c_cppFunc = new MyC_CppFunc();
TextView tv = findViewById(R.id.tv_show);
tv.setText(c_cppFunc.stringFromJNI(6, 2));
到了這里,關(guān)于如何在現(xiàn)有的 Android Studio 工程中添加 C++ 代碼的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!