android-ndk 数据传递
来源:互联网 发布:单农男装网络旗舰店 编辑:程序博客网 时间:2024/05/18 00:44
首先定义DataProvider
package com.example.testndkpassdata;public class DataProvider {/** * 把两个java中的int传递给c语言, c语言处理完毕后,把相加的结果返回给java * @param x * @param y * @return */public native int add(int x ,int y);public static native int sub(int x ,int y);public native char add(char x, char y); //String /** * 把java中的string传递给c语言, c语言获取到java中的string之后 ,在string后面添加 一个hello 字符串 * @param s * @return */public native String sayHelloInC(String s);/** * 把java中的一个int数组 传递给c语言,c语言处理完毕这个java数组 * 把int数组中的每一个元素+10 ; * 然后把结果返回给java * @param iNum * @return */public native int[] intMethod(int[] iNum); public native byte[] byteMethod(byte[] iByte);public native DiskInfo getStruct();}编译生成C/C++头文件
1、在控制台下进入工作路径,本工程路径为:E:\work\java\workspace\testndkpassdata。
2、运行javah 命令:javah -classpath E:\work\java\workspace\JavaJni com.example.testndkpassdata ChangeMethodFromJni
本文生成的C/C++头文件名为: com_example_testndkpassdata_DataProvider.h
生成C/C++头文件之后,你就需要写头文件对应的本地方法。注意:所有的本地方法的第一个参数都是指向JNIEnv结构的。这个结构是用来调用JNI函数的。第二个参数jclass的意义,要看方法是不是静态的(static)或者实例(Instance)的。前者,jclass代表一个类对象的引用,而后者是被调用的方法所属对象的引用。
返回值和参数类型根据等价约定映射到本地C/C++类型,如表JNI类型映射所示。有些类型,在本地代码中可直接使用,而其他类型只有通过JNI调用操作。
JNI通过JNIEnv提供的操作Java数组的功能。它提供了两个函数:一个是操作java的简单型数组的,另一个是操作对象类型数组的。
因为速度的原因,简单类型的数组作为指向本地类型的指针暴露给本地代码。因此,它们能作为常规的数组存取。这个指针是指向实际的Java数组或者Java数组的拷贝的指针。另外,数组的布置保证匹配本地类型。
为了存取Java简单类型的数组,你就要要使用GetXXXArrayElements函数(见表B),XXX代表了数组的类型。这个函数把Java数组看成参数,返回一个指向对应的本地类型的数组的指针。
当你对数组的存取完成后,要确保调用相应的ReleaseXXXArrayElements函数,参数是对应Java数组和GetXXXArrayElements返回的指针。如果必要的话,这个释放函数会复制你做的任何变化(这样它们就反射到java数组),然后释放所有相关的资源。
为了使用java对象的数组,你必须使用GetObjectArrayElement函数和SetObjectArrayElement函数,分别去get,set数组的元素。GetArrayLength函数会返回数组的长度。
使用对象JNI提供的另外一个功能是在本地代码中使用Java对象。通过使用合适的JNI函数,你可以创建Java对象,get、set 静态(static)和实例(instance)的域,调用静态(static)和实例(instance)函数。JNI通过ID识别域和方法,一个域或方法的ID是任何处理域和方法的函数的必须参数。
表C列出了用以得到静态(static)和实例(instance)的域与方法的JNI函数。每个函数接受(作为参数)域或方法的类,它们的名称,符号和它们对应返回的jfieldID或jmethodID。
/* DO NOT EDIT THIS FILE - it is machine generated */#include <jni.h>/* Header for class com_example_testndkpassdata_DataProvider */#ifndef _Included_com_example_testndkpassdata_DataProvider#define _Included_com_example_testndkpassdata_DataProvider#ifdef __cplusplusextern "C" {#endif/* * Class: com_example_testndkpassdata_DataProvider * Method: add * Signature: (II)I */JNIEXPORT jint JNICALL Java_com_example_testndkpassdata_DataProvider_add__II (JNIEnv *, jobject, jint, jint);/* * Class: com_example_testndkpassdata_DataProvider * Method: sub * Signature: (II)I */JNIEXPORT jint JNICALL Java_com_example_testndkpassdata_DataProvider_sub (JNIEnv *, jclass, jint, jint);/* * Class: com_example_testndkpassdata_DataProvider * Method: add * Signature: (CC)C */JNIEXPORT jchar JNICALL Java_com_example_testndkpassdata_DataProvider_add__CC (JNIEnv *, jobject, jchar, jchar);/* * Class: com_example_testndkpassdata_DataProvider * Method: sayHelloInC * Signature: (Ljava/lang/String;)Ljava/lang/String; */JNIEXPORT jstring JNICALL Java_com_example_testndkpassdata_DataProvider_sayHelloInC (JNIEnv *, jobject, jstring);/* * Class: com_example_testndkpassdata_DataProvider * Method: intMethod * Signature: ([I)[I */JNIEXPORT jintArray JNICALL Java_com_example_testndkpassdata_DataProvider_intMethod (JNIEnv *, jobject, jintArray);/* * Class: com_example_testndkpassdata_DataProvider * Method: byteMethod * Signature: ([B)[B */JNIEXPORT jbyteArray JNICALL Java_com_example_testndkpassdata_DataProvider_byteMethod (JNIEnv *, jobject, jbyteArray);JNIEXPORT jobject JNICALL Java_com_example_testndkpassdata_DataProvider_getStruct (JNIEnv *, jobject);#ifdef __cplusplus}#endif#endif
package com.example.testndkpassdata;public class DiskInfo { public String name; public int serial; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getSerial() { return serial; } public void setSerial(int serial) { this.serial = serial; } }
#include<stdio.h>#include<jni.h>#include "com_example_testndkpassdata_DataProvider.h";#include <android/log.h>#include<malloc.h>#define LOG_TAG "System.out.c"#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)/** * 返回值 char* 这个代表char数组的首地址 * Jstring2CStr 把java中的jstring的类型转化成一个c语言中的char 字符串 */char* Jstring2CStr(JNIEnv* env, jstring jstr) {char* rtn = NULL;jclass clsstring = (*env)->FindClass(env, "java/lang/String"); //Stringjstring 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 jint JNICALL Java_com_example_testndkpassdata_DataProvider_add__II(JNIEnv * env, jobject obj, jint x, jint y) {LOGD("x=%d", x);LOGD("y=%d", y);return x + y;}JNIEXPORT jstring JNICALL Java_com_example_testndkpassdata_DataProvider_sayHelloInC(JNIEnv * env, jobject obj, jstring jstr) {/*//在c语言中 是没有java的String char* cstr = Jstring2CStr(env, jstr); LOGD("cstr=%s",cstr); // c语言中的字符串 都是以'/0' 作为结尾 char arr[7]= {' ','h','e','l','l','o','\0'}; strcat(cstr,arr); LOGD("new cstr=%s",cstr); return (*env)->NewStringUTF(env,cstr);*/const char* szStr = (*env)->GetStringUTFChars(env, jstr, 0);// c语言中的字符串 都是以'/0' 作为结尾char arr[7] = { ' ', 'h', 'e', 'l', 'l', 'o', '\0' };strcat(szStr, arr);(*env)->ReleaseStringUTFChars(env, jstr, szStr);return (*env)->NewStringUTF(env, szStr);}/**env java 虚拟机 结构体c实现的指针 包含的有很多jni方法 *jobject obj 代表的是调用这个c代码的java对象 代表的是DataProider的对象 */JNIEXPORT jintArray JNICALL Java_com_example_testndkpassdata_DataProvider_intMethod(JNIEnv * env, jobject obj, jintArray arr) {//1.知道数组的长度//2.操作这个数组里面的每一个元素int len = (*env)->GetArrayLength(env, arr);LOGD("shuzu len =%d", len);// jint* (*GetIntArrayElements)(JNIEnv*, jintArray, jboolean*);jint* intarr = (*env)->GetIntArrayElements(env, arr, NULL);int i = 0; //c99for (; i < len; i++) {//*(intarr+i) += 10;LOGD("intarr[%d]=%d", i, intarr[i]);intarr[i] += 10;}// void (*ReleaseIntArrayElements)(JNIEnv*, jintArray,// jint*, jint);//(*env)->ReleaseIntArrayElements(env, arr, intarr, NULL); // c语言释放掉 刚才申请的内存空间return arr;}/** * 代表的是调用c代码 的class类 * jclass DataProvider 类 */JNIEXPORT jint JNICALL Java_com_example_testndkpassdata_DataProvider_sub(JNIEnv * env, jclass clazz, jint x, jint y) {LOGD("x=%d", x);LOGD("y=%d", y);return x - y;}//返回一个结构,这里返回一个硬盘信息的简单结构类型JNIEXPORT jobject JNICALL Java_com_example_testndkpassdata_DataProvider_getStruct(JNIEnv *env, jobject obj) {/* 下面为获取到Java中对应的实例类中的变量*///获取Java中的实例类jclass objectClass = (*env)->FindClass(env,"com/example/testndkpassdata/DiskInfo");jmethodID m = (*env)->GetMethodID(env,objectClass,"<init>","()V");jobject Diskobj=(*env)->NewObject(env,objectClass,m);//获取类中每一个变量的定义//名字jfieldID str = (*env)->GetFieldID(env,objectClass, "name", "Ljava/lang/String;");//序列号jfieldID ival = (*env)->GetFieldID(env,objectClass, "serial", "I");//给每一个实例的变量付值(*env)->SetObjectField(env,Diskobj, str, (*env)->NewStringUTF(env,"my name is D:"));(*env)->SetIntField(env,Diskobj, ival, 10);//(*env)->DeleteLocalRef(env, m);//(*env)->DeleteLocalRef(env, str);//(*env)->DeleteLocalRef(env, ival);//(*env)->DeleteLocalRef(env, objectClass);return Diskobj;}测试文件
package com.example.testndkpassdata;import android.app.Activity;import android.os.Bundle;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.Toast;public class MainActivity extends Activity implements OnClickListener{ static{ System.loadLibrary("Hello"); } private Button bt1,bt2,bt3,bt4,bt5; private DataProvider provider; private DiskInfo diskInfo; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); bt1 = (Button) this.findViewById(R.id.bt1); bt2 = (Button) this.findViewById(R.id.bt2); bt3 = (Button) this.findViewById(R.id.bt3); bt4 = (Button) this.findViewById(R.id.bt4); bt5=(Button)this.findViewById(R.id.bt5); bt1.setOnClickListener(this); bt2.setOnClickListener(this); bt3.setOnClickListener(this); bt4.setOnClickListener(this); bt5.setOnClickListener(this); provider = new DataProvider(); diskInfo=new DiskInfo(); } public void onClick(View v) { switch (v.getId()) { case R.id.bt1: int result = provider.add(3, 5); Toast.makeText(this, "相加的结果"+result, 1).show(); break; case R.id.bt2: String str = provider.sayHelloInC("zhangsan "); Toast.makeText(this, str, 1).show(); break; case R.id.bt3: int[] arr = {1,2,3,4,5}; provider.intMethod(arr); for(int i=0;i<arr.length;i++){ Toast.makeText(this, "java "+ arr[i], 1).show(); System.out.println("java "+ arr[i]); } break; case R.id.bt4: int subresult = DataProvider.sub(5, 3); Toast.makeText(this, "相减的结果"+subresult, 1).show(); break; case R.id.bt5: DiskInfo diskInfo=provider.getStruct(); Toast.makeText(this, "结果name:"+diskInfo.getName()+"\nserial:"+diskInfo.getSerial(), 1).show(); break; } }}demo下载地址http://download.csdn.net/detail/maweisky531/9064183
- android-ndk 数据传递
- android NDK --java 与 C 语言之间传递数据
- android(NDK+JNI)---Android使用JNI实现Java与C之间传递数据
- Android NDK开发(四)——Java传递数据到C
- Android Studio NDK 入门教程(2)--Java与C++之间的简单数据转换与传递
- Android JNI和NDK学习(08)--JNI实例一 传递基本类型数据
- Android JNI和NDK学习(08)--JNI实例一 传递基本类型数据
- Android NDK 学习之传递类对象
- Android NDK中数据类型传递使用
- Android - Intent - 传递数据
- Android 数据传递Bundle
- Android Bundle数据传递
- Android - Intent - 传递数据
- android javaScript数据传递
- Android传递ArrayList数据
- Android传递数据
- android-数据传递
- android Application 数据传递
- TextView加载Html内容(自定义TextView)
- 微信公众号开发系列-网页授权获取用户基本信息
- Linux 下 安装 PHP 的 PDO_MYSQL 扩展
- LOJ 1201 - A Perfect Murder(二分匹配 最大独立集)
- IOS项目上架时问题的解决方案(3)
- android-ndk 数据传递
- 解决点击状态栏时ScrollView自动滚动到初始位置失效办法
- 腾讯云使用教程 基本工具 开发工具软件 从入门到精通 图文教程
- python抓取网页的一个小例子
- 2.6/ 7 精确表示浮点数 + 最大公约数
- HDU 5071 Chat (神一般的模拟题)
- C++类型转换小疑惑
- zoj 3820 求三遍树的中心
- 联想键盘功能键不好使,看这里