JNI C++ 开发流程概要

一.生成.h文件

  1. win+x,运行 cmd,cd  java工程class文件所在bin文件夹
  2. 运行 javah -classpath .\ -jni <classes>
  3. bin文件夹的同级目录生成<classes>.h文件
  4. vs2010打开<classes>.h文件,<jni.h> 修改为 "jni.h"
  5. vs2010 新建 <classes>.cpp文件,编写JNI本地 函数

二.JNI本地函数编写细则

  • java String 参数传递
  1. char* jstringToWindows( JNIEnv *env, jstring jstr )
    { //UTF8/16转换成gb2312
        int length = (env)->GetStringLength(jstr );
        const jchar* jcstr = (env)->GetStringChars(jstr, 0 );
        char* rtn = (char*)malloc( length*2+1 );
        int size = 0;
        size = WideCharToMultiByte( CP_ACP, 0, (LPCWSTR)jcstr, length, rtn,(length*2+1), NULL, NULL );
        if( size <= 0 )
            return NULL;
        (env)->ReleaseStringChars(jstr, jcstr );
        rtn[size] = 0;
        return rtn;
    }
  2. jstring WindowsTojstring( JNIEnv* env, const char* str )
    {//gb2312转换成utf8/16
        jstring rtn = 0;
        int slen = strlen(str);
        unsigned short * buffer = 0;
        if( slen == 0 )
            rtn = (env)->NewStringUTF(str );
        else
        {
            int length = MultiByteToWideChar( CP_ACP, 0, (LPCSTR)str, slen, NULL, 0 );
            buffer = (unsigned short *)malloc( length*2 + 1 );
            if( MultiByteToWideChar( CP_ACP, 0, (LPCSTR)str, slen, (LPWSTR)buffer, length ) >0 )
                rtn = (env)->NewString(  (jchar*)buffer, length );
        }
        if( buffer )
            free( buffer );
        return rtn;
    }
  •  c++ 结构体与java 类的对应关系
  1. java没有结构体的概念,若JNI函数需反馈结构体变量,则java调用层需定义相应的class
  2. 结构体内嵌结构体,对应class内嵌class. 

        结构体定义:

        typedef struct _VoiceAPIStat 
        {
             int            nSLESRecOpenSucceedCnt;       
             int            nSLESRecOpenFailedCnt;       
             int            nSLESPlayOpenSucceedCnt; 
         }VoiceAPIStat;
         //-------------------------------------------------------------------------------------------------------
        typedef struct _EngRunInfoStat
        {
               bool                bStatisticsEnable;  
               int                nStatisticsLevel;    
               int                nRptIntervalInMs;  
               VoiceAPIStat            stVoiceApiStat; 
         }EngRunInfoStat;

         Java类相应定义:

         public class EngRunInfoStat

         {
              public boolean      bStatisticsEnable;  
              public int      nStatisticsLevel; 
              public int     nRptIntervalInMs;
              public VoiceAPIStat     stVoiceApiStat;
    
              public class VoiceAPIStat           

              {
                    public int        nSLESRecOpenSucceedCnt; 
                    public int        nSLESRecOpenFailedCnt;        
                    public int        nSLESPlayOpenSucceedCnt;  
              };
         };

      3.结构体内嵌结构体数组,对应类内嵌类数组

  • 基本数据类型常用操作函数(JNI调用事例)

                (env)->SetBooleanField(objectEng,nGroup,GroupNo);
                (env)->SetDoubleField(objectEng,dwQu,Qu);
                jstr = WindowsTojstring(env,“test”);
                (env)->SetObjectField(objectEng,chNote,jstr);
                (env)->SetCharField(objectEng,wNum,Number);

        GetBooleanField 获取不同数据类型字段值  相关函数

  • 对象数组操作示例(结构体参数值反馈java类)

                jobjectArray InfoAry = 0;
                jsize jNum = pItem->GetNumber();
                InfoAry = (env)->NewObjectArray(jNum, objClass, 0); 

                jclass jInfo = (env)->FindClass("test/common/docu/taglnfo");
                //获取成员变量
                jmethodID InitInfoID = (env)->GetMethodID(jInfo, "<init>", "()V");
                jobject  objInfo;

                jfieldID strName = (env)->GetFieldID(jInfo, "strName", "Ljava/lang/String;");
                jfieldID nWave = (env)->GetFieldID(jInfo, "nWave ", "I");

                for (int j = 0; j < jNum; j++)
                {
                    objInfo = (env)->NewObject(jInfo ,InitInfoID);

                    jstr = WindowsTojstring(env, Name);
                    (env)->SetObjectField(objInfo ,strName,jstr);
                    (env)->SetIntField(objInfo ,nWave ,nLen);

                    (env)->SetObjectArrayElement(InfoAry, j, objInfo );
                }

                赋值上一级(InfoAry 为一个Object成员)

                (env)->SetObjectField(objectEng,TestInfoArray,InfoAry);

三.基本相关的cmd命令

  • 查看签名
  1. cd  java工程bin文件夹;
  2. 运行 javap -s 类全名(e.g. "test.common.document.tagHead")
  3. 类全名获取方式: 将该类点开,然后选中类名,右键选择copy qualified name.(eclipse)
  4. 内嵌类的签名比较特殊,首先是L开头代表类,然后包名,外部类与内部类签名之间用$隔开,即“Lcom/test/eng/EngRunInfoStat$VoiceAPIStat;”

  相关网站链接:http://www.ceeger.com/Script/AndroidJNI/AndroidJNI.html

        

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值