java 传递脚本给c_[置顶] JNI之java传递数据给c语言

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

/* 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只做声明.)

c62628886c6403b1491c7e4f7c82e83f.png

下面是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

#include

#include

#include "com_pl_ndkpassdata_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__)

/**

* 用于把java中的String转换成c可用的指向字符的指针类型

*/

/**

* 中的指针函数:

* 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

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

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:

android:layout_width="fill_parent"

android:layout_height="fill_parent"

android:orientation="vertical" >

android:id="@+id/bt1"

android:layout_width="fill_parent"

android:layout_height="wrap_content"

android:text="传递两个int给c代码" />

android:id="@+id/bt2"

android:layout_width="fill_parent"

android:layout_height="wrap_content"

android:text="传递string给c代码" />

android:id="@+id/bt3"

android:layout_width="fill_parent"

android:layout_height="wrap_content"

android:text="传递int数组给c代码" />

android:id="@+id/bt4"

android:layout_width="fill_parent"

android:layout_height="wrap_content"

android:text="调用静态native方法" />

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值