jni编程细节记录

相信做jni开发的人都知道,jni是什么意思,接口本地调用。

本文记录下本人在开发中关于jni编程中用c++代码编写的简单调用以及复杂数据的调用等等会遇到的一些问题已经解决办法


1、jni简单调用:

首先要在java中定义本地接口,然后在.c或.c++文件中进行编写接口实现的代码。

但是要注意的是c与c++在编写的时候还有差别。

在jni 的JNIEnv,是一个全局的指针,我们在编写的时候通过这个对象来进行jni方法的调用

就拿一个最简单的例子:生成一个java 环境String字符串

c++:

env->NewStringUTF("hahaha");

c:

	(*env)->NewStringUTF(env,"hahaha")

2、jni使用回调:

回调的使用是通过我们传过来的对象的类的方法来实现回调的,
 JNIEXPORT void JNICALL Java_cp_com_jnidemo_JniFirst_jniCallBack
   (JNIEnv *env, jobject srcobj, jdouble a, jdouble b , jobject job){
    jclass cla = env->GetObjectClass(job);
    jmethodID mid = env->GetMethodID(cla,"callBack","(Ljava/util/String)V");
    char buffer[20];
    snprintf(buffer,20,"%f",a*b);//将double类型转换为char
    jstring native_desc = env->NewStringUTF(buffer);
    env->CallVoidMethod(job,mid,native_desc);
   }

可以看到最后一个参数job就是我们传过来的回调接口的对象,通过获取他的类,他的回调方法,然后执行回调,但是现在就有一个问题,也就是获取他方法的时候里边的第三个参数  (
"(Ljava/util/String)V"
这个如何确定呢,现在这个是String类型的,那么如果是int等等呢。
说一下这个参数这样写的意义: 括号里边是回调的时候参数的个数以及类型的签名 ,最后代表当前回调方法有没有返回值V 代表没有返回值.
如果是一个参数的话那么他的写法就是: (回调数据的类型)+返回值类型 
String                      "(Ljava/util/String)V"
int                            "(I)V"
boolean              "(Z)V"

那么如果回调的数据类型是一个数组的时候:
String                 "([Ljava/util/String)V"   也就是在前边加一个大括号

int                         “([I)V”
boolean              "([Z)V"
也就是都加一个大括号就好了

jni签名:

JNI签名:

类型签名

Java 类型

类型签名

Java 类型

Z

boolean

[

[]

B

byte

[I

int[]

C

char

[F

float[]

S

short

[B

byte[]

I

int

[C

char[]

J

long

[S

short[]

F

float

[D

double[]

D

double

[J

long[]

L

fully-qualified-class(全限定的类)

[Z

boolean[]

 

 

 

 

 

 

 

 

 

 

 

 

 

 

l  基本类型

以特定的大写字母表示

3、传递数组:

JNIEXPORT jint JNICALL Java_cp_com_jnidemo_JniFirst_jniArray
   (JNIEnv *env, jobject obj, jintArray jarray){
    int i,sum = 0;
    jsize len = env->GetArrayLength(jarray);
    jint* body = env->GetIntArrayElements(jarray,0);
    for(int i = 0;i < len;i++){
        sum = body[i]+sum;
    }
    //释放引用对象的空间,防止内存溢出
    env->ReleaseIntArrayElements(jarray,body,0);
    return sum;
   }

  要注意释放对象。 

4 、复杂对象的传递:

JNIEXPORT void JNICALL Java_cp_com_jnidemo_JniFirst_setPeopleInfo
  (JNIEnv *env, jobject srcobj, jobject obj){
  jclass cla = env->GetObjectClass(obj);
    if(cla ==NULL){
  cout<<"GetObjectClass failed \n";
    }

    jfieldID ageID = env->GetFieldID(cla,"age","I");//获取年龄id
    jfieldID nameID = env->GetFieldID(cla,"name","Ljava/lang/String;");

    jint age = env->GetIntField(obj,ageID);
    jstring name= (jstring)env->GetObjectField(obj,nameID);
    const char * c_name = env->GetStringUTFChars(name,NULL);
    string str_name = c_name;
      LOGI("%d", age);
      LOGI("%s",c_name);
    env->ReleaseStringUTFChars(name,c_name);
    cout<<"native age isL "<< age <<"nam is"<< str_name<<endl;

  }
首先要获取到当前传过来的jobject的类型,然后获取相应的方法,进行设置。

5、传递HashMap对象:

JNIEXPORT void JNICALL Java_cp_com_jnidemo_JniFirst_putMap
  (JNIEnv *env, jobject obj,  jobject jmap,jobject callback){

      jclass c_map = env->FindClass("java/util/Map");
      jmethodID m_getSize = env->GetMethodID(c_map,"size","()I");
      jint jsize = env->CallIntMethod(jmap,m_getSize);
      LOGI("%d",jsize);
        char log_str[128];
        jmethodID m_isempty = env->GetMethodID(c_map,"isEmpty","()Z");
        jboolean b= env->CallBooleanMethod(jmap,m_isempty);

           if(b){
           LOGI("map集合为空");
           }else{
            LOGI("map集合不为空");
           }

         jmethodID m_get = env->GetMethodID(c_map,"clear","()V");
         if(m_get == 0){
          LOGI("没有找到CLEAR这个方法");
         }else{
        env->CallVoidMethod(jmap,m_get);
         LOGI("执行lCLEAR这个方法");
         jmethodID size = env->GetMethodID(c_map,"size","()I");

         jint s = env->CallIntMethod(jmap,size);
         int i =s;
         LOGI("%d",s);
         jclass call_class = env->GetObjectClass(callback);
                 jmethodID mid = env->GetMethodID(call_class,"callBack","(I)V");
                  char* result = (char*)malloc(s); //malloc是void类型,可以强转成任意类型
                  //char* tag= "执行完clear以后的结果size =";
                 // strcat(tag,result);//将俩个字符指针的字符串拼接
                  env->CallVoidMethod(callback,mid,s);
         }


     }
需要注意的就是签名,还有各种类型的相互转化。


下边我把我写的Demo地址: http://download.csdn.net/detail/u012808234/9552808
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值