1.首先创建 DataProvider类:

package com.pl.ndkpassdata;

public class DataProvider {
static{
System.loadLibrary("passdata");//加载库
} /**
* 把两个java中的int传递给c语言, c语言处理完毕后,把相加的结果返回给java
*/
public native int add(int x,int y);
/**
* 静态方法 c语言处理减法运算 返回结果给java
*/
public static native int sub(int x,int y);
/**
* 把java中的string传递给c语言, c语言获取到java中的string之后 ,在string后面添加 一个hello 字符串
*/
public native String getHelloString(String s);
/**
* 把java中的一个int数组 传递给c语言,c语言处理完毕这个java数组
* 把int数组中的每一个元素+10,然后把结果返回给java
*/
public native int[] getIntArr(int[] iNum); }

2.创建完毕后找到它.class位置,生成JNI样式的头文件:

com_pl_ndkpassdata_DataProvider.h:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_pl_ndkpassdata_DataProvider */ #ifndef _Included_com_pl_ndkpassdata_DataProvider
#define _Included_com_pl_ndkpassdata_DataProvider
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_pl_ndkpassdata_DataProvider
* Method: add
* Signature: (II)I
*/
JNIEXPORT jint JNICALL Java_com_pl_ndkpassdata_DataProvider_add
(JNIEnv *, jobject, jint, jint); /*
* Class: com_pl_ndkpassdata_DataProvider
* Method: sub
* Signature: (II)I
*/
JNIEXPORT jint JNICALL Java_com_pl_ndkpassdata_DataProvider_sub
(JNIEnv *, jclass, jint, jint); /*
* Class: com_pl_ndkpassdata_DataProvider
* Method: getHelloString
* Signature: (Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_pl_ndkpassdata_DataProvider_getHelloString
(JNIEnv *, jobject, jstring); /*
* Class: com_pl_ndkpassdata_DataProvider
* Method: getIntArr
* Signature: ([I)[I
*/
JNIEXPORT jintArray JNICALL Java_com_pl_ndkpassdata_DataProvider_getIntArr
(JNIEnv *, jobject, jintArray); #ifdef __cplusplus
}
#endif
#endif

上面是用javah -jni命令生成的。

3.  在项目的根目录创建jni目录(和src,bin等目录平级);

1.拷贝com_pl_ndkpassdata_DataProvider.h到jni目录下;

2.在jni目录下创建Android.mk文件和passdata.c文件;(关于c语言的.c和.h文件的区别是 :函数定义要放在.c中,而.h只做声明.)

下面是Android.mk的内容:

 LOCAL_PATH := $(call my-dir)

   include $(CLEAR_VARS)

   LOCAL_MODULE    := passdata
LOCAL_SRC_FILES := passdata.c
#liblog.c
LOCAL_LDLIBS += -llog
include $(BUILD_SHARED_LIBRARY)

下面是passdata.c

#include <stdio.h>
#include <jni.h>
#include <stdlib.h>
#include "com_pl_ndkpassdata_DataProvider.h"
#include <android/log.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__) /**
* 用于把java中的String转换成c可用的指向字符的指针类型
*/
/**
* <jni.h>中的指针函数:
* jclass (*FindClass)(JNIEnv*, const char*); //拿到一个类
* jstring (*NewStringUTF)(JNIEnv*, const char*);//拿到一个String对象
* jmethodID (*GetMethodID)(JNIEnv*, jclass, const char*, const char*);//拿到类的方法
* jobject (*CallObjectMethod)(JNIEnv*, jobject, jmethodID, ...);//调用类的方法
* jsize (*GetArrayLength)(JNIEnv*, jarray);//拿到数组的长度
* jbyte* (*GetByteArrayElements)(JNIEnv*, jbyteArray, jboolean*); //转换成c可用的byte指针类型
*/
char* Jstring2CStr(JNIEnv * env,jstring s){ //JNIEnv*:java虚拟机的结构体c语言实现的指针,包含的有很多jni方法
char* rtn = NULL;
jclass classstring = (*env)->FindClass(env,"java/lang/String"); //调用java中的String类
jstring strencode = (*env)->NewStringUTF(env,"GB2312"); //拿到编码格式
//拿到方法 。参数2:指定类,参数3:方法名,参数4:(Ljava/lang/String;)是getBytes的参数;[B代表是返回值是一个byte数组
jmethodID mid = (*env)->GetMethodID(env,classstring,"getBytes","(Ljava/lang/String;)[B");
jbyteArray barr = (jbyteArray)(*env)->CallObjectMethod(env,s,mid,strencode);//相当于调用java的getBytes
//拿到byte数组的长度
jsize size = (*env)->GetArrayLength(env,barr);
jbyte* ba = (*env)->GetByteArrayElements(env,barr,JNI_FALSE);
if(size > 0){
rtn = (char*)malloc(size+1); //申请一块内存 //+"\0"
memcpy(rtn,ba,size); //拷贝字符串
rtn[size]=0; //'\0'
}
(*env)->ReleaseByteArrayElements(env,barr,ba,0);//释放内存空间
return rtn;
}
JNIEXPORT jint JNICALL Java_com_pl_ndkpassdata_DataProvider_add
(JNIEnv * env, jobject obj, jint x, jint y){
LOGD("add()x:%d,y:%d",x,y);
return x+y;
} JNIEXPORT jint JNICALL Java_com_pl_ndkpassdata_DataProvider_sub
(JNIEnv * env, jclass clazz, jint x, jint y){
LOGD("sub()x:%d,y:%d",x,y);
return x-y;
} JNIEXPORT jstring JNICALL Java_com_pl_ndkpassdata_DataProvider_getHelloString
(JNIEnv * env, jobject obj, jstring s){
char* cs = Jstring2CStr(env,s);
LOGD("cs=%s",cs);
char carr[7] = {' ','h','e','l','l','o','\0'};
strcat(cs,carr); //拼接
LOGD("new cs=%s",cs);
LOGD("end getHelloString()");
return (*env)->NewStringUTF(env,cs);
} //jsize (*GetArrayLength)(JNIEnv*, jarray); //拿到数组长度
// jint* (*GetIntArrayElements)(JNIEnv*, jintArray, jboolean*) //转换成c可用的int指针类型
JNIEXPORT jintArray JNICALL Java_com_pl_ndkpassdata_DataProvider_getIntArr
(JNIEnv * env, jobject obj, jintArray jarr){
jsize len = (*env)->GetArrayLength(env,jarr);
LOGD("len=%d",len);
jint* carr = (*env)->GetIntArrayElements(env,jarr,JNI_FALSE);
int i;
for(i=0;i<len;i++){
*(carr+i)+=10;
}
LOGD("end getIntArr()");
return jarr;
}

完成映射实现,使用Cygwin生成.so库文件.基本完成了,别忘了clean下项目。

基本到这做完了。下面是测试代码:

MainActivity.java

package com.pl.ndkpassdata;

import android.os.Bundle;
import android.app.Activity;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast; public class MainActivity extends Activity implements OnClickListener{
private Button bt1,bt2,bt3,bt4;
private DataProvider provider;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.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); bt1.setOnClickListener(this);
bt2.setOnClickListener(this);
bt3.setOnClickListener(this);
bt4.setOnClickListener(this);
provider = new DataProvider();
}
public void onClick(View v) {
switch (v.getId()) {
case R.id.bt1:
int result = provider.add(10, 10);
Toast.makeText(this, "相加的结果:"+result, 1).show();
break; case R.id.bt2:
String str = provider.getHelloString("pengliang");
Toast.makeText(this, str, 1).show();
break;
case R.id.bt3:
int[] arr = {7,8,9,10,6};
provider.getIntArr(arr);
String arrtostr ="[";
for(int i=0;i<arr.length;i++){
arrtostr+=arr[i]+",";
}
arrtostr +="]";
Toast.makeText(this, arrtostr, 1).show();
break;
case R.id.bt4:
int subresult = DataProvider.sub(100, 24);
Toast.makeText(this, "相减的结果:"+subresult, 1).show();
break;
}
}
}

main.xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" > <Button
android:id="@+id/bt1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="传递两个int给c代码" /> <Button
android:id="@+id/bt2"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="传递string给c代码" /> <Button
android:id="@+id/bt3"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="传递int数组给c代码" /> <Button
android:id="@+id/bt4"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="调用静态native方法" /> </LinearLayout>

[置顶] JNI之java传递数据给c语言的更多相关文章

  1. Android NDK 开发(四)java传递数据到C【转】

    转载请注明出处:http://blog.csdn.net/allen315410/article/details/41845701 前面几篇文章介绍了Android NDK开发的简单概念.常见错误及处 ...

  2. [置顶] think in java interview-高级开发人员面试宝典(二)

    从现在开始,以样题的方式一一列出各种面试题以及点评,考虑到我在前文中说的,对于一些大型的外资型公司,你将会面临全程英语面试,因此我在文章中也会出现许多全英语样题. 这些题目来自于各个真实的公司,公司名 ...

  3. [置顶] NS2中对TCP数据包和ACK包的TCP Sink类的主要实现代码详尽剖析--吐血放送

    NS2中对TCP数据包和ACK包的TCP Sink类的主要实现代码详尽剖析,限于个人水平,如有错误请留言指出! TcpSink类的recv()方法: void TcpSink::recv(Packet ...

  4. 【Redis】解析Redis和Java传递数据

    在Java中使用Redis之前需要导入 jedis.jar 包,由于Redis是基于key-value进行数据存储,java中的数据存储到Redis中有许多方式,这里笔者介绍采用JSON字符串和对象序 ...

  5. [置顶] 我的 Java 后端书架 (2016 年暖冬版)

    转自:  http://calvin1978.blogcn.com/articles/bookshelf16.html 我的 Java 后端书架 (2016 年暖冬版) 本书架主要针对 Java 后端 ...

  6. [置顶] DataGridView控件---绑定数据方法

             DataGridView控件是在windows应用程中显示数据最好的方式,它只需要几行简短的代码就可以把数据显示给用户,同时又支持增.删.改操作.今天将自己总结的增加数据的方法总结分 ...

  7. [置顶] think in java interview-高级开发人员面试宝典(八)

    面经出了7套,收到许多读者的Email,有许多人说了,这些基础知识是不是为了后面进一步的”通向架构师的道路“做准备的? 对的,你们没有猜错,就是这样的,我一直在酝酿后面的”通向架构师的道路“如何开章. ...

  8. [置顶] think in java interview-高级开发人员面试宝典(一)

    “生死六重门” 无论你是在职,非在职,高级工程师,工程师,架构师,如果你正在面试阶段,请看完此文! 相信这篇文章对你的职业生涯和阶值观会造成重大的改变! 如果你是一名PM或者是管理者正在物色合适的开发 ...

  9. [置顶] think in java interview-高级开发人员面试宝典代码示例

    下载资源地址为: http://download.csdn.net/detail/lifetragedy/6379755 这是think in java interview中的代码示例,包括JAVA基 ...

随机推荐

  1. Objective-c 协议(protocol)

    协议的作用类似地C++中对抽象基类的多重继承.类似于Java中的接口(interface)的概念.   协议是多个类共享方法的列表,协议中列出的方法在本类中并没有相应实现,而是别的类来实现这些方法. ...

  2. Objective-c 程序结构

    类是Objective-c的核心,Objective-c程序都是围绕类进行的.Objective-c程序至少包含以下三个部分: 1.类接口:定义了类的数据和方法,但是不包括方法的实现代码. 2.类实现 ...

  3. Java多线程之synchronized(四)

    前面几章都是在说synchronized用于对象锁,无论是修饰方法也好修饰代码块也好,然而关键字synchronized还可以应用到static静态方法上,如果这样写,那就是对当前的*.java文件所 ...

  4. [译]在 64bit 环境中执行32 bit的SSIS包

    最近碰到了一个众所周知的32bit的 SSIS 包在64bit的SQL Server环境的执行问题. 我看了一些解决方案,比如修改在SSDT里面修改 debug 选项(Run64BitRuntime ...

  5. C - N皇后问题(搜索)

    Description 在N*N的方格棋盘放置了N个皇后,使得它们不相互攻击(即任意2个皇后不允许处在同一排,同一列,也不允许处在与棋盘边框成45角的斜线上. 你的任务是,对于给定的N,求出有多少种合 ...

  6. linux driver: input子系统

    <韦东山Linux视频第2期_从零写驱动\第13课第1节 输入子系统概念介绍_P.wmv> 本视频对输入子系统的结构进行了详细的剖析,通过本视频,可以了解到input核心包括了设备和han ...

  7. mac下面xcode+ndk7配置cocos2dx & box2d的跨ios和android平台的游戏教程

    这篇教程是介绍如何使用cocos2d-x和box2d来制作一个demo,且此demo能同时运行于ios和android平台.在继续阅读之前,建议您先阅读上一篇教程. 首先,按照上一篇教程,搭建好mac ...

  8. r语言之给定的概率密度函数生成随机数

    假设概率密度函数为: 思路: 首先产生-1到1之间的均匀分布随机数x,和0到1之间的均匀分布随机数y. 如果y<f(x),则x是符合该概率密度的随机数,否则,重复上述操作. 用r语言生成100个 ...

  9. iOS开发之SDWebImage详解

    介绍 github地址: https://github.com/rs/SDWebImage 简介 一个异步图片下载及缓存的库 特性: 一个扩展UIImageView分类的库,支持加载网络图片并缓存图片 ...

  10. 如何去掉Protel99se汉化菜单

    说明: 安装Protel99se汉化包后,卸载后重新安装也无法去掉汉化菜单.本文介绍解决办法. 问题: 网上一些Protel99se的安装包内,在介绍Protel安装时,采用3大步的方法.第一步安装P ...