android与ndk交互,NDK-JNI与Java的交互 hello-world

前言

在前面NDK-CMake初探中我介绍了下Android Studio搭建NDK环境的步骤,当环境搭建起来以后,我们就可以开始编写native代码与Java层进行互相交互了,下面我就来简单的介绍下如何native与Java如何进行交互。

来自native层的hello world

编写Java层代码

使用native可以修饰一个native方法,表示这个函数在c/c++中实现,System.loadLibrary();用于加载so文件。

package org.ndk.ndkfirst;

public class NDKTest {

static {

System.loadLibrary("ndk-test-lib");

}

/**

* native返回一个字符串给Java层

*/

public native String getStringFromNative();

}

编写相应的native代码

要想编写C/C++代码,我们首先得知道Java层的native修饰函数对应的C/C++表现形式。命名规则如下:

JNIEXPORT 返回值类型 JNICALL Java_包名_类名_函数名(JNIEnv * env, jobject obj)

上面例子中的getStringFromNative方法按照这个规则就是如下形式

JNIEXPORT jstring JNICALL Java_org_ndk_ndkfirst_NDKTest_getStringFromNative(JNIEnv * env, jobject obj);

JNIEXPORT JNICALL都是jni的关键字,表示此函数是要被jni调用的,而jstring为jni中定义的一个类型,对应Java中的String。

参数列表中的第一个参数JNIEnv* 是定义任意native函数的第一个参数(包括调用JNI的RegisterNatives函数注册的函数),指向JVM函数表的指针,函数表中的每一个入口指向一个JNI函数,每个函数用于访问JVM中特定的数据结构。JNIEnv是一个与线程相关的变量,不同线程的JNIEnv彼此独立。

第二个参数有一点特殊,对于普通函数(非static修饰),为jobject,表示当前的对象,如果是静态函数,为jclass,表示当前类。

通过上面的分析,我们可以写出如下的native代码:

#include

extern "C"

{

JNIEXPORT jstring JNICALL

Java_org_ndk_ndkfirst_NDKTest_getStringFromNative

(JNIEnv *env, jobject obj) {

//NewStringUTF表示创建一个utf-8格式的字符串

return env->NewStringUTF("hello world from native~~~");

}

}

接下来按照NDK-CMake初探中的介绍配置好CMakeLists.txt文件即可。

cmake_minimum_required(VERSION 3.4.1)

#设置生成的so动态库最后输出的路径

set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI})

add_library(ndk-test-lib

SHARED

src/main/cpp/ndk_test.cpp)

find_library(log-lib

Specifies the name of the NDK library that

log)

target_link_libraries(ndk-test-lib ${log-lib} )

调用JNI函数和调用普通函数没有什么区别。如下。

NDKTest mNDKTest = new NDKTest();

Log.i(TAG, mNDKTest.getStringFromNative());

使用javah命令生成头文件

在上面介绍了JNI函数的命名规则,下面就来介绍一个使用javah命令来生成所需要的函数形式的方法。javah命令格式

javah -classpath [path1] -jni [path2]

首先介绍下path2参数,path2为含有的native方法的完整类路径,对于上面的例子,就是如下形式:

org.ndk.ndkfirst.NDKTest

path1需要指定path2完整类路径的绝对路径。比如上面的NDKTest.java文件在C:\NDKFirst\app\src\main\java\org\ndk\ndkfirst\NDKTest.java下面,那么path1就应该为C:\NDKFirst\app\src\main\java

所以最后的命令如下,最后生成的.h文件在C:\NDKFirst\app\src\main\java下,里面就有我们需要的JNI函数,copy一下就行了。

javah -classpath "C:\Users\Jay\Desktop\NDKFirst\app\src\main\java" -jni org.ndk.ndkfirst.NDKTest

/* DO NOT EDIT THIS FILE - it is machine generated */

#include

/* Header for class org_ndk_ndkfirst_NDKTest */

#ifndef _Included_org_ndk_ndkfirst_NDKTest

#define _Included_org_ndk_ndkfirst_NDKTest

#ifdef __cplusplus

extern "C" {

#endif

/*

* Class: org_ndk_ndkfirst_NDKTest

* Method: getStringFromNative

* Signature: ()Ljava/lang/String;

*/

JNIEXPORT jstring JNICALL Java_org_ndk_ndkfirst_NDKTest_getStringFromNative

(JNIEnv *, jobject);

#ifdef __cplusplus

}

#endif

#endif

Demo地址:github

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值