您的位置:首页 > 移动开发 > Android开发

Ndk基础知识(二)Ndk基本使用流程

2018-01-24 16:32 369 查看
本篇博文基于前一篇Ndk基础知识(一)环境搭建编写,有需要的读者请先阅读前一篇博文。

预备知识

在AndroidStudio自动生成的项目中,我们猜想stringFromJNI()和cpp文件中的Java_com_breeze_ndkdemo2_MainActivity_stringFromJNI是对应的,事实上确实如此。根据JNI的命名规则,java层的native方法命名规则为在返回类型前加native,如

public native String stringFromJNI();


对应的c++方法命名为对应的返回类型+类的全名(包名+类名,其中将”.”换成”_”)+方法名+(JNIEnv *env, jobject thiz + 参数)如:

jstring
Java_com_breeze_ndkdemo2_MainActivity_stringFromJNI(
JNIEnv *env, jobject /* this */)


生成java方法对应的c层的方法名看起来比较复杂,其实也有对应的工具可以使用,java提供了javah可以自动生成java native方法对应的c头文件。

在Android Studio中可以设置该命令。操作如下:File->Settings->Tools->External Tools中选择加号添加一个工具,在该窗口中进行如下设置



设置完成后,我们看如何使用:

首先写好java类,Build->Make Project生成相关类文件,这一步很重要,javah是根据class 文件去生成头文件的,所以必须先生成相应的class文件。然后对该类右键选择External Tools->javah生成相应的头文件,按照当前配置,生成的头文件会放在jni目录中。事实上得到头文件后放在哪个位置可根据需要自己重新剪切调整,甚至不使用头文件直接把该方法声明拿去使用也是可以的,javah命令只是方便我们不用去写容易出错的方法名罢了。

举例

新建一个NativeUtils类内容如下:

public class NativeUtils {
public static native int addNum(int num);
public static native String addChar(String str);
public static native int[] addArray(int[] arr, int length);
}


Build->Make Project,生成class文件,右键External Tools->javah生成对应的头文件,在native-lib.cpp文件中实现上述方法。

#include <jni.h>
#include <string>
#include <android/log.h>
#include <string.h>
#include "com_breeze_ndkdemo2_NativeUtils.h"
extern "C"
jstring
Java_com_breeze_ndkdemo2_MainActivity_stringFromJNI(
JNIEnv *env,
jobject /* this */) {
std::string hello = "Hello from C++";
return env->NewStringUTF(hello.c_str());
}

JNIEXPORT jint JNICALL Java_com_breeze_ndkdemo2_NativeUtils_addNum
(JNIEnv *, jclass, jint num){
return num + 1;
}

/*
* Class:     com_breeze_ndkdemo2_NativeUtils
* Method:    addChar
* Signature: (Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_breeze_ndkdemo2_NativeUtils_addChar
(JNIEnv *env , jclass, jstring str){
jsize alen = env->GetStringLength(str);
char * strs = new char[alen + 1];
jboolean isCopy = true;
const jchar* chars = env->GetStringChars(str, &isCopy);
for (int i = 0; i < alen; i++){
strs[i] = chars[i];
}
__android_log_write(ANDROID_LOG_INFO, "str from java", strs);
std::string s = "hello";
return env->NewStringUTF(s.c_str());
}

/*
* Class:     com_breeze_ndkdemo2_NativeUtils
* Method:    addArray
* Signature: ([I)[I
*/
JNIEXPORT jintArray JNICALL Java_com_breeze_ndkdemo2_NativeUtils_addArray
(JNIEnv *env, jclass, jintArray array, jint length){
jboolean isCopy = true;
jint* arr = env->GetIntArrayElements(array, &isCopy);
for (int i = 0; i < length; i++){
arr[i] = arr[i] + 1;
}
jintArray javaArray;
javaArray = env->NewIntArray(length);
env->SetIntArrayRegion(javaArray, 0, length, arr);
return javaArray;
}


在MainActivity中调用:

public class MainActivity extends AppCompatActivity {

// Used to load the 'native-lib' library on application startup.
static {
System.loadLibrary("native-lib");
}

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

// Example of a call to a native method
TextView tv = (TextView) findViewById(R.id.sample_text);
tv.setText(stringFromJNI());
int num = NativeUtils.addNum(3);
Log.d("ZXX", num + "");
String str = NativeUtils.addChar("hello");
Log.d("ZXX", str);
int [] arr = NativeUtils.addArray(new int[]{1, 2, 3}, 3);
for (int i = 0; i < arr.length; i++){
Log.d("ZXX", "num" + i + ":" + arr[i]);
}
}

/**
* A native method that is implemented by the 'native-lib' native library,
* which is packaged with this application.
*/
public native String stringFromJNI();

}


上述内容介绍了简单数据类型和字符串在c和java之间的传递。其中jint,jstring,jintArray是java中的int,String,int[]在c中对应类型,这些内容定义在jni.h中。下面列出c和java中部分类型的对应关系:

Java类型本地类型描述
booleanjbooleanC/C++8位整型
bytejbyteC/C++带符号的8位整型
charjcharC/C++无符号的16位整型
shortjshortC/C++带符号的16位整型
intjintC/C++带符号的32位整型
longjlongC/C++带符号的64位整型e
floatjfloatC/C++32位浮点型
doublejdoubleC/C++64位浮点型
Objectjobject任何Java对象,或者没有对应java类型的对象
ClassjclassClass对象
Stringjstring字符串对象
Object[]jobjectArray任何对象的数组
boolean[]jbooleanArray布尔型数组
byte[]jbyteArray比特型数组
char[]jcharArray字符型数组
short[]jshortArray短整型数组
int[]jintArray整型数组
long[]jlongArray长整型数组
float[]jfloatArray浮点型数组
double[]jdoubleArray双浮点型数组
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  ndk android