android 向c 传参数,一步一步学习androidNDK编程(java给c传递数据)

这篇已经是"一步一步学习androidNDK编程"的第四篇了,在这篇中,我们将会在java中传递代码给c代码。

首先,我们新建一个android工程"ndkdata",

第一步:

同样的首先声明native方法,如下:

public native int add(int a,int b);

public native String helloSir(String name);

public native int[] intMethod(int[] intArray); 可以看到我这里声明了三个方法,用来传递不同的数据类型给c代码

第二步:

由于我们的这些方法都是声明在MainActivity.java中的,所以我们需要首先将该MainActivity.java用javac编译为.class文件,然后运用javah,生成对应的.h头文件。

将该MainActivity.java用javac编译为.class文件:这个就是运行该android工程即可在bin/classes目录下生成对应的.class文件。

命令行下进入bin/classes所在的目录:执行javah com.example.ndkdata.MainActivity即可在该目录下生成对应的com_example_ndkdata_MainActivity.h头文件了,内容如下:

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

#include

/* Header for class com_example_ndkdata_MainActivity */

#ifndef _Included_com_example_ndkdata_MainActivity

#define _Included_com_example_ndkdata_MainActivity

#ifdef __cplusplus

extern "C" {

#endif

/*

* Class: com_example_ndkdata_MainActivity

* Method: add

* Signature: (II)I

*/

JNIEXPORT jint JNICALL Java_com_example_ndkdata_MainActivity_add

(JNIEnv *, jobject, jint, jint);

/*

* Class: com_example_ndkdata_MainActivity

* Method: helloSir

* Signature: (Ljava/lang/String;)Ljava/lang/String;

*/

JNIEXPORT jstring JNICALL Java_com_example_ndkdata_MainActivity_helloSir

(JNIEnv *, jobject, jstring);

/*

* Class: com_example_ndkdata_MainActivity

* Method: intMethod

* Signature: ([I)[I

*/

JNIEXPORT jintArray JNICALL Java_com_example_ndkdata_MainActivity_intMethod

(JNIEnv *, jobject, jintArray);

#ifdef __cplusplus

}

#endif

#endif      接下来我们在ndkdata工程中,创建jni目录,然后再将刚才生成的com_example_ndkdata_MainActivity.h文件拷贝到该目录下,然后创建我们的c代码:hello.c

将com_example_ndkdata_MainActivity.h中生成的方法添加到hello.c文件中这里需要添加参数,因为默认生成的只有方法的参数类型,没有参数对象,并且引入对应的头文件,如下:

#include

#include

#include "com_example_ndkdata_MainActivity.h"

JNIEXPORT jint JNICALL Java_com_example_ndkdata_MainActivity_add

(JNIEnv * env, jobject obj, jint x, jint y) {

}

JNIEXPORT jstring JNICALL Java_com_example_ndkdata_MainActivity_helloSir

(JNIEnv * env, jobject obj, jstring jstr) {

}

JNIEXPORT jintArray JNICALL Java_com_example_ndkdata_MainActivity_intMethod

(JNIEnv * env, jobject obj, jintArray arr) {

}接下来就是实现我们的c代码了,如下:

#include

#include

#include "com_example_ndkdata_MainActivity.h"

JNIEXPORT jint JNICALL Java_com_example_ndkdata_MainActivity_add

(JNIEnv * env, jobject obj, jint x, jint y) {

return x+y;

}

/**

* 返回值 char* 这个代表char数组的首地址

*  Jstring2CStr 把java中的jstring的类型转化成一个c语言中的char 字符串

*/

char*   Jstring2CStr(JNIEnv*   env,   jstring   jstr)

{

char*   rtn   =   NULL;

jclass   clsstring   =   (*env)->FindClass(env,"java/lang/String"); //String

jstring   strencode   =   (*env)->NewStringUTF(env,"GB2312");  // 得到一个java字符串 "GB2312"

jmethodID   mid   =   (*env)->GetMethodID(env,clsstring,   "getBytes",   "(Ljava/lang/String;)[B"); //[ String.getBytes("gb2312");

jbyteArray   barr=   (jbyteArray)(*env)->CallObjectMethod(env,jstr,mid,strencode); // String .getByte("GB2312");

jsize   alen   =   (*env)->GetArrayLength(env,barr); // byte数组的长度

jbyte*   ba   =   (*env)->GetByteArrayElements(env,barr,JNI_FALSE);

if(alen   >   0)

{

 rtn   =   (char*)malloc(alen+1);         //"\0"

 memcpy(rtn,ba,alen);

 rtn[alen]=0;

}

(*env)->ReleaseByteArrayElements(env,barr,ba,0);  //

return rtn;

}

JNIEXPORT jstring JNICALL Java_com_example_ndkdata_MainActivity_helloSir

(JNIEnv * env, jobject obj, jstring jstr) {

//在c语言中 是没有java的String

char* cstr = Jstring2CStr(env, jstr);

// c语言中的字符串 都是以'\0' 作为结尾

char arr[7]= {' ','h','e','l','l','o','\0'};

strcat(cstr,arr);

return (*env)->NewStringUTF(env,cstr);

}

JNIEXPORT jintArray JNICALL Java_com_example_ndkdata_MainActivity_intMethod

(JNIEnv * env, jobject obj, jintArray arr) {

}

编写完了hello.c之后,需要编写Android.mk,内容如下:

#交叉编译编译c/c++代码所依赖的配置文件

#获取当前Android.mk的路径

LOCAL_PATH := $(call my-dir)

#变量初始化操作

include $(CLEAR_VARS)

#libhello.so 其实生成的libhello.so就是在我们这个模块的名称前面加上lib后边加上.so

LOCAL_MODULE := hello

LOCAL_SRC_FILES := hello.c

include $(BUILD_SHARED_LIBRARY)      现在就需要在cygwine的命令行下进入该工程ndkdata的根目录下,执行"ndk-build"命令生成对应的可直接运行的二进制文件,注意每次在执行"ndk-build"之后最好将android工程clean一下。

在“ndk-build”成功之后,需要在java代码中引入这些库文件:

static {

System.loadLibrary("hello");

}

注意这里的"hello",就是我们在Android.mk文件中写的模块名,即LOCAL_MODULE的值。

现在,就可以执行声明的native方法了,在java代码中直接调用即可,是不是很简单呢。

原文:http://blog.csdn.net/mockingbirds/article/details/45157431

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值