当前位置: 首页 > news >正文

温州专业微网站制作报价/实体店营销策划方案

温州专业微网站制作报价,实体店营销策划方案,网络营销方案分析,房产销售网站设计前面几篇文章介绍了Android NDK开发的简单概念、常见错误及处理和从第一个Hello World开始实际做一个简单的JNI开发示例,相信看完之后,大家对NDK开发有了一个概念上的认识了,那么接下来我们需要再深入一下NDK的开发,我们知道NDK开…

前面几篇文章介绍了Android NDK开发的简单概念、常见错误及处理和从第一个Hello World开始实际做一个简单的JNI开发示例,相信看完之后,大家对NDK开发有了一个概念上的认识了,那么接下来我们需要再深入一下NDK的开发,我们知道NDK开发就是使用JNI这层“协议”在Java和C之间起个“桥梁”的作用,将Java和Native C之间联立起来,让Java和C直接的数据进行互调。谈到Java和C之间的数据调用,那么Java是怎样传递数据到C中的呢,C拿到数据处理完后又怎样将处理后的数据回传给Java的呢?先别急,接下来我们就看看Java怎么传递数据给C的。

1,建立一个Android工程,在工程下建立一个DataProvider类,在这个类里定义3个native方法,如下:

package com.example.ndktransferdata;

public class DataProvider {

/**

* 把两个java中的int传递给C语言,c语言处理完毕后,把相加的结果返回给java

*

* @param x

* @param y

* @return

*/

public native int add(int x, int y);

/**

* 把java中的String传递给c语言,c语言获取后,在string后面添加一个hello字符串,返回给java

*

* @param s

* @return

*/

public native String sayHelloInC(String s);

/**

* 把java中的一个int数组传递给C语言,C语言接收这个数组,把int数组中的每一个元素+10,然后返回给Java

*

* @param iNum

* @return

*/

public native int[] intMethod(int[] iNum);

}

2,用Javah编译头文件

7ad7f2097fc3a396b81d12cf23554d66.png

做到这一步发现了一个问题,从描述上看应该是编码错误,这里错误的使用了GBK来编译java文件了,改成UTF-8就没问题,只要在javah命令后面添加 -encoding utf-8,为编译器提供编码环境就行,下面是改正后的结果:

6378d20d7e89e20c9bc61e1198764fc7.png

说明native代码的函数签名已经生成了,我们将这个生成的函数签名头文件剪切到jni目录下,在c代码中引用这个头文件就好了。

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

#include 

/* Header for class com_example_ndktransferdata_DataProvider */

#ifndef _Included_com_example_ndktransferdata_DataProvider

#define _Included_com_example_ndktransferdata_DataProvider

#ifdef __cplusplus

extern "C" {

#endif

/*

* Class:     com_example_ndktransferdata_DataProvider

* Method:    add

* Signature: (II)I

*/

JNIEXPORT jint JNICALL Java_com_example_ndktransferdata_DataProvider_add

(JNIEnv *, jobject, jint, jint);

/*

* Class:     com_example_ndktransferdata_DataProvider

* Method:    sayHelloInC

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

*/

JNIEXPORT jstring JNICALL Java_com_example_ndktransferdata_DataProvider_sayHelloInC

(JNIEnv *, jobject, jstring);

/*

* Class:     com_example_ndktransferdata_DataProvider

* Method:    intMethod

* Signature: ([I)[I

*/

JNIEXPORT jintArray JNICALL Java_com_example_ndktransferdata_DataProvider_intMethod

(JNIEnv *, jobject, jintArray);

#ifdef __cplusplus

}

#endif

#endif

3,编写C语言代码

之前在第二步的时候我们编译好了函数签名的头文件,所以这里我们就需要用过头文件中的方法签名了,一共包含3个这样的native函数,函数里实现是这样的:

#include

#include

#include

#include

#include"com_example_ndktransferdata_DataProvider.h"

#include

#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"); //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 jint JNICALL Java_com_example_ndktransferdata_DataProvider_add(

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_ndktransferdata_DataProvider_sayHelloInC(

JNIEnv * env, jobject obj, jstring jstr) {

char* cstr = Jstring2CStr(env, jstr);

LOGD("cstr = %s", cstr);

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

strcat(cstr, arr);

LOGD("new cstr = %s", cstr);

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

}

JNIEXPORT jintArray JNICALL Java_com_example_ndktransferdata_DataProvider_intMethod(

JNIEnv * env, jobject obj, jintArray jarr) {

//获取传递进来数组的长度

int len = (*env)->GetArrayLength(env, jarr);

//获取传递进来数组的元素,即数组首地址

jint* intArr = (*env)->GetIntArrayElements(env, jarr, 0);

int i = 0;

for (; i 

//打印处理前的数组元素

LOGD("intArr[%d] = %d", i, intArr[i]);

//遍历数组元素+10

*(intArr + i) += 10;

}

return jarr;

}

4,配置Android.mk文件

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := Hello

LOCAL_SRC_FILES := Hello.c

LOCAL_LDLIBS += -llog

include $(BUILD_SHARED_LIBRARY)

光配置Android.mk文件大致就可以了,但是还需要解决一个版本兼容问题,做法是在jni目录下新建Application.mk文件,加上

APP_PLATFORM := android-8

5,编译C语言代码

736aadb01020f365ba9fcce43db145f9.png

6,Java代码中处理返回的数据

Java中传递数据到C代码中,C代码处理完后返回给Java,这时候Java拿到数据后就可以做自己的一些业务操作了,首先我们编译完Native代码后,先Refresh一下工程,然后clean一下工程,编写如下的测试案例:

public class MainActivity extends Activity implements OnClickListener {

// 加载本地库文件

static {

System.loadLibrary("Hello");

}

private Button btn1, btn2, btn3;

private DataProvider provider;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

btn1 = (Button) findViewById(R.id.btn1);

btn2 = (Button) findViewById(R.id.btn2);

btn3 = (Button) findViewById(R.id.btn3);

btn1.setOnClickListener(this);

btn2.setOnClickListener(this);

btn3.setOnClickListener(this);

provider = new DataProvider();

}

@Override

public void onClick(View v) {

switch (v.getId()) {

case R.id.btn1 : // 传递2个int给C代码

int result = provider.add(3, 5);

Toast.makeText(this, "相加的结果:" + result, 0).show();

break;

case R.id.btn2 : // 传递string给C代码

String str = provider.sayHelloInC("zhang san");

Toast.makeText(this, str, 0).show();

break;

case R.id.btn3 : // 传递int数组给C代码

int[] arr = {1, 2, 3, 4, 5};

provider.intMethod(arr);

for (int i = 0; i 

System.out.println("arr[" + i + "] = " + arr[i]);

}

break;

default :

break;

}

}

}

运行一下工程,注意:这里只能开启arm模拟器,如果是x86模拟器会安装apk时候报错,因为这段native代码只编写了arm支持的版本,没有支持x86。如果在运行测试的时候出现一些错误的话,请参考上篇文章中提示慢慢解决。Android NDK开发——常见错误集锦以及LOG使用

测试1:Java传递2个int给C

de6c5a7b87bf1e1faa20464958c78acf.png

Logcat输出:

eca1a0f50cb8cf66db2ca113e1f82fa6.png

测试2:Java传递string给C

8373bec6cdb9e8dc0f2393bddf7217dc.png

Logcat输出:

261ba12055fe7f0c620524ea1cb33586.png

测试3:Java传递int数组给C

Logcat输出:

2ace4f8715cecd6f1a09e6c281b58b38.png

总结:

上述这个简单的示例可以说明ndk开发中,Java是怎样将数据传递给C代码的了,程序中只是简单的介绍了3种数据类型int,string和int[],这是远远不够的,因为Java支持的数据类型比较多,这时候怎么办?好,有了上面的例子,我们可以举一反三了,在之前的博客中我也强调过ndk解压包下的jni.h这个文件的重要性,这个文件不仅仅定义了Java数据类型在C语言中的表示,看一下源码,就发现一种一一映射的关系:

......

typedef uint8_t         jboolean;       /* unsigned 8 bits */

typedef int8_t          jbyte;          /* signed 8 bits */

typedef uint16_t        jchar;          /* unsigned 16 bits */

typedef int16_t         jshort;         /* signed 16 bits */

typedef int32_t         jint;           /* signed 32 bits */

typedef int64_t         jlong;          /* signed 64 bits */

typedef float           jfloat;         /* 32-bit IEEE 754 */

typedef double          jdouble;        /* 64-bit IEEE 754 */

#else

typedef unsigned char   jboolean;       /* unsigned 8 bits */

typedef signed char     jbyte;          /* signed 8 bits */

typedef unsigned short  jchar;          /* unsigned 16 bits */

typedef short           jshort;         /* signed 16 bits */

typedef int             jint;           /* signed 32 bits */

typedef long long       jlong;          /* signed 64 bits */

typedef float           jfloat;         /* 32-bit IEEE 754 */

typedef double          jdouble;        /* 64-bit IEEE 754 */

......

另外还有一个非常重要的结构体JNINativeInterface,这里面定义了很多C函数,只要看懂大致意思就可以试着去调用这些函数,这些函数在native开发中显得特别重要:

......

jbooleanArray (*NewBooleanArray)(JNIEnv*, jsize);

jbyteArray    (*NewByteArray)(JNIEnv*, jsize);

jcharArray    (*NewCharArray)(JNIEnv*, jsize);

jshortArray   (*NewShortArray)(JNIEnv*, jsize);

jintArray     (*NewIntArray)(JNIEnv*, jsize);

jlongArray    (*NewLongArray)(JNIEnv*, jsize);

jfloatArray   (*NewFloatArray)(JNIEnv*, jsize);

jdoubleArray  (*NewDoubleArray)(JNIEnv*, jsize);

jboolean*   (*GetBooleanArrayElements)(JNIEnv*, jbooleanArray, jboolean*);

jbyte*      (*GetByteArrayElements)(JNIEnv*, jbyteArray, jboolean*);

jchar*      (*GetCharArrayElements)(JNIEnv*, jcharArray, jboolean*);

jshort*     (*GetShortArrayElements)(JNIEnv*, jshortArray, jboolean*);

jint*       (*GetIntArrayElements)(JNIEnv*, jintArray, jboolean*);

jlong*      (*GetLongArrayElements)(JNIEnv*, jlongArray, jboolean*);

jfloat*     (*GetFloatArrayElements)(JNIEnv*, jfloatArray, jboolean*);

jdouble*    (*GetDoubleArrayElements)(JNIEnv*, jdoubleArray, jboolean*);

......

源码比较长,有兴趣的朋友自己翻看一下,这里只贴部分。

http://www.lbrq.cn/news/953479.html

相关文章:

  • wordpress不能进后台/宁波seo教程网
  • 成都 视频网站建设/域名停靠网页app推广大全
  • 网站空间 php程序/十八未成年禁用免费app
  • 浙江省网站icp备案/软文范例大全100字
  • 重庆石柱网站设计公司/怎么免费搭建自己的网站
  • 服装电子商务网站版式设计/指数型基金
  • 做网站网站如何定位/seo优化师培训
  • 什么是营销网站/南昌seo优化公司
  • 怎么免费创建一个网站/google永久免费的服务器
  • 苏州做网站优化的/发软文
  • 中小企业网站建设好么/百度app下载链接
  • 网站建设行业的趋势/宁波谷歌seo推广
  • 住房建设部官方网站设计费计取/广州网络推广服务商
  • 斗图制作器/抖音搜索seo
  • 动态网站建设实训心得/网站自助建站系统
  • 用qt做网站可以吗/建站工具有哪些
  • 怎样建设自己网站的后台/谷歌seo引擎优化
  • 众筹网站开发/天津疫情最新消息
  • 服饰营销型网站建设/全网关键词搜索
  • 建网站用什么浏览器/百度总部电话
  • 快手app下载安装免费下载/抖音seo排名优化公司
  • 闵行网站建设公司纸/明星百度指数在线查询
  • 手机登录网站后台/网络营销案例范文
  • 178网站建设/百度搜索收录
  • 做视频可以领钱的网站/谷歌网页版入口在线
  • 做网站的流程前端做什么/全网热搜榜第一名
  • 网站开发流程步骤 口袋/近几天的新闻摘抄
  • 智慧团建网站入口pc端/销售课程视频免费
  • 闵行区网站/百度一下你就知道官网百度
  • wordpress固定链接设置失败/网站优化员seo招聘
  • 用户虚拟地址空间布局架构
  • Taro 路由相关 API 详解与实战
  • Elasticsearch 简化指南:GCP Google Compute Engine
  • 【音视频协议篇】RTSP系列
  • 我用Cursor,1周上线了一个虚拟资料流量主小程序技术选型
  • Linux 密码生成利器:pwgen 命令详解