r;
}
3、注意:
①、在c中接收java中int类型的数据时:由于int类型的数据java和c中的长度相同,c可以直接使用java传递过来int型数据。
②、c接收了java中的字符串数据 ,由于c中没有字符串类型,首先c要先将java的字符串类型转成char数组类型;
在c语言中 字符串的结果都是以/0这样一个标示 作为字符串的结尾
下面是具体的转换方法:
/**
* 工具方法
* 作用: 把java中的string 转化成一个c语言中的char数组
* 接受的参数 envjni环境的指针
* jstr 代表的是要被转化的java的string 字符串
* 返回值 : 一个c语言中的char数组的首地址 (char 字符串)
*/
char* Jstring2CStr(JNIEnv* env, jstring jstr)
{
char* rtn = NULL;
jclass clsstring = (*env)->FindClass(env,"java/lang/String");
jstring strencode = (*env)->NewStringUTF(env,"GB2312");
jmethodID mid =
(*env)->GetMethodID(env,clsstring,"getBytes","(Ljava/lang/String;)[B");
// String.getByte("GB2312");
jbyteArray barr=
(jbyteArray)(*env)->CallObjectMethod(env,jstr,mid,strencode);
jsize alen = (*env)->GetArrayLength(env,barr);
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;
}
③、在将java 中int类型的数组传递c代码中 ,获取数组的长度,再获取数组的首地址后获取每一个元素。
④、java不会将字符串数组传给c代码, 而是将字符串数组元素用:隔开转成字符串传给c代码.
十二、c代码调用java代码:案例:c代码调用java 代码 弹出一个土司.
主要步骤:首先java调用c代码的方法 在c代码中再调用java代码:
1、在java类中定义方法:
public class DemoActivity extends Activity {
static{
System.loadLibrary("Hello");
}
public native void callMethod1();
//按钮的点击事件
public void showToast(View view){
//1.调用底层的c代码
//2.c代码里面 让c语言的代码调用java代码 显示出来一个土司
callMethod1();
}
//被c调用的方法
public void javaShowToast(String message){
Toast.makeText(this, message, 0).show();
}
}
2、c代码:类似java中的反射,先获取java类的字节码文件,再获取method对象,再执行该方法。
#include
#include "cn_itcast_ndkcallback_DemoActivity.h"
#include
#define LOG_TAG "System.out"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,__VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG,__VA_ARGS__)
//参数env 是JNIEnv的指针
// obj 代表的是调用这个c代码的java对象
JNIEXPORT void JNICALLJava_cn_itcast_ndkcallback_DemoActivity_callMethod1
(JNIEnv * env , jobject obj) {
// 找到 java中的代码javaShowToast 调用他 让java代码显示出来一个土司
//
// Method method = DemoActivity.class.getMethod("javaShowToast",new Class[]{String.class});
// method.invoke(obj, "string");
// 1. 寻找要调用的java代码的字节码 class
//jclass (*FindClass)(JNIEnv*, const char*);
//获取java的类的字节码。FindClass方法参数(env ,java类类路径)
jclass jclazz = (*env)->FindClass(env,"cn/itcast/ndkcallback/DemoActivity");
// 2.寻找当前jclass里面的方法的id
// jmethodID (*GetMethodID)(JNIEnv*, jclass, const char*,const char*);
//获取字节码中指定方法的id。GetMethodID方法参数(env ,字节码文件,方法名, 该方法签名)
//方法签名通过javap 工具获得;
jmethodID jshowtoastmethod =
(*env)->GetMethodID(env,jclazz,"javaShowToast","(Ljava/lang/String;)V");
//3. 调用该方法
// void (*CallVoidMethod)(JNIEnv*, jobject, jmethodID, ...);
//执行方法:CallVoidMethod方法参数(env,obj ,方法id,传递到被调用java方法中的参数)
(*env)->CallVoidMethod(env,obj,jshowtoastmethod,(*env)->NewStringUTF(env,"hi from c"));
}
3、注意: 获取方法签名的方法是:在命令行中使用javap 工具:
命令为: javap -s 完整类名 。 就可以获取指定类中所有方法的方法签名。
十二、c代码调用java代码方法的常见案例:
1、定义被c代码调用的java的方法
public class DataProvider{
//C调用java空方法
public voidhelloFromJava(){
System.out.println("我是java的空方法");
}
//C调用java中的带两个int参数的方法
public int Add(int x,int y){
int result =x+y;
System.out.println("相加的结果为"+result);