android-jni与java参数传递

来源:互联网 发布:哈佛大学 知乎 编辑:程序博客网 时间:2024/05/21 10:05


http://blog.csdn.net/andyhuabing/article/details/7551230


android-jni与java参数传递

===================================================================================================
问题的来源:
jni与java层之间互传参数,有几个问题需要解决:
1、需要传递的参数的函数非常多,达到100个左右
2、传递的参数有些比较复杂,涉及到结构的嵌套
3、参数有输入参数与输出参数两种

举函数例子如下:
/*-- 授权信息 --*/
typedef struct {
    int  m_dwProductID;   /* 普通授权的节目ID */    
    int  m_tBeginDate;    /* 授权的起始时间 */
    int  m_tExpireDate;   /* 授权的过期时间 */
    char m_bCanTape;      /* 用户是否购买录像:1-可以录像;0-不可以录像 */
    char m_byReserved[3]; /* 保留 */
}CAEntitle;


结构嵌套结构,比较复杂
/*-- 授权信息集合 --*/
typedef struct {
    int        m_wProductCount;
    char       m_m_byReserved[2];    /* 保留 */
    CAEntitle  m_Entitles[300];      /* 授权列表 */
}SCDCAEntitles;


前面两个是输入参数,后面两个是输出参数
extern boolean STBCA_SCPBRun( const char* pbyCommand, 
 int       wCommandLen,  
 char*     pbyReply,  
 int*      pwReplyLen  );


问题解决方案1:
常用方案,
A、C++调用传递参数给java层
   调用成员函数利用CallxxxMethodYYY(其中xxx表示返回数据类型,YYY表代码V/A)
   其参数可以直接利用函数传,也可采用GetFieldID&SetObjectField配对使用
   即如下方案:
struct CATestOffsets
{
   jfieldID    name;
   jfieldID    vendor;
   jfieldID    version;
   jfieldID    handle;
   jfieldID    m_tBeginDate;
   jfieldID    m_tExpireDate;
   ....
   
   jmethodID  STBCA_SCPBRunCallXX;
   jmethodID  ....
} gSensorOffsets;   
  利用jfieldID和jmethodID表示java类的成员变量及成员函数。。。。工作量相当大,调试也很麻烦
  
B、JAVA调用C++代码
通过做法就是定义一堆的native函数,然后将参数传递一一定义传递下来
对于结构在java层定义类,在jni层进行转换,首先可能传递的参数很多,而且每个函数都要小心写,
对于需要既需要输入参数又需要输出参数的,很麻烦哟。。非常痛苦。

这种方案做了两天,实在受不了,太多native函数,大多jmethodID与jfieldID,而且同时输入及输出。

确认让人很头痛噻!


问题解决方案2:
重点就是利用C++层分配共享内存空间,函数参数非常简单,只需要返回值,所有参数传递利用共享内存搞定


这利方式对于参数的传递非常方便,只是需要注意地址及偏移值(addr:offset),代码比较清晰。
但对于native函数及jmethodID与jfieldID的处理还是很麻烦呀!不对对于参数处理简化了很多了。


基本代码如下,我这里搞了个最复杂的传递结构参数举例:



Java 代码编写如下

[java] view plain copy print?
  1. <span style="font-size:16px;">  /** 
  2.      * 按长度进行缓冲区分配空间 
  3.      * @param length: buffer length  
  4.      * @return start address 
  5.      */  
  6.     public int AllocStructMem(int length){  
  7.         if (length % 4 != 0) {  
  8.             length -= (length % 4);  
  9.             length += 4;  
  10.         }  
  11.         if ((address = native_alloc(length)) == 0)  
  12.             throw new RuntimeException();  
  13.           
  14.         return address;  
  15.     }     
  16.       
  17.     /** 
  18.      * 释放缓冲区空间 
  19.      * @param ptr:start address 
  20.      */  
  21.     public void FreeStructMem(int ptr){  
  22.         if(ptr == 0x00){  
  23.             throw new NullPointerException("NULL pointer");  
  24.         }  
  25.           
  26.         native_free(ptr);  
  27.     }  
  28.       
  29.     public int DSSetInt(int ptr,int offset,int value) {  
  30.         if(ptr == 0x00){  
  31.             throw new NullPointerException("NULL pointer");  
  32.         }  
  33.           
  34.         return native_setInt(ptr,offset,4,value);  
  35.     }  
  36.       
  37.     public int DSSetBytes(int addr,int off,int len,byte[] b){  
  38.         return native_setBytes(addr,off, len, b);  
  39.     }  
  40.   
  41.     public void DSSetUTFString(int addr,int off, int len, String s) {  
  42.         DSSetBytes(addr,off, len, s.getBytes());  
  43.     }  
  44.       
  45.     public int DSGetInt(int addr,int off, int len) {  
  46.         if(off < 0 || len <= 0 || addr == 0x00 )  
  47.             throw new IllegalArgumentException();  
  48.           
  49.         return native_getInt(addr, off, len);  
  50.     }  
  51.   
  52.     public int DSGetBytes(int addr,int off, int len, byte[] b) {  
  53.         if (off < 0 || len <= 0 || addr == 0x00 ||b == null || b.length < len)  
  54.             throw new IllegalArgumentException();  
  55.           
  56.         return native_getBytes(addr, off, len, b);  
  57.     }  
  58.   
  59.     public String DSGetUTFString(int addr,int off, int len) {  
  60.         if (off < 0 || len <= 0 )  
  61.             throw new IllegalArgumentException();  
  62.           
  63.         byte[] b = new byte[len];  
  64.         native_getBytes(addr, off, len, b);  
  65.         return new String(b);  
  66.     }     
  67.       
  68.     private static native int native_alloc(int length);  
  69.     private static native void native_free(int ptr);  
  70.     private static native int native_setInt(int addr, int offset, int len,  
  71.             int value);  
  72.     private static native int native_setBytes(int addr, int offset, int len,  
  73.             byte[] b);  
  74.     private static native int native_getInt(int addr, int offset, int len);  
  75.     private static native int native_getBytes(int addr, int offset, int len,  
  76.             byte[] b);</span>  


下面是测试代码:

[java] view plain copy print?
  1. <span style="font-size:16px;">  // C++ 定义结构  
  2.     //  struct mmm_t {  
  3.     //      int a;  
  4.     //      int b[4];  
  5.     //      struct {  
  6.     //          int c1, c2;  
  7.     //      } c;  
  8.     //      struct {  
  9.     //          int d1;  
  10.     //          char*d2;  
  11.     //      } d[2];  
  12.     //      float e;  
  13.     //  };  
  14.       
  15.     static class cc{  
  16.         int c1;  
  17.         int c2;  
  18.     }  
  19.       
  20.     static class dd{  
  21.         int d1;  
  22.         byte[] d2 = new byte[64];  
  23.     };  
  24.       
  25.     static class mmm_t{  
  26.         int a;  
  27.         int[] b = new int[4];  
  28.         cc c[] = new cc[1];  
  29.         dd d[] = new dd[2];  
  30.         int e;  
  31.         dd darr[] = new dd[10];  
  32.   
  33.         public void mmm_malloc(){  
  34.             c[0] = new cc();  
  35.             for(int i=0;i<2;i++){  
  36.                 d[i] = new dd();  
  37.             }  
  38.             for(int i=0; i < 10; i++){  
  39.                 darr[i] = new dd();  
  40.             }  
  41.         }  
  42.     }  
  43.       
  44.     public int complexStructTest(){  
  45.         mmm_t m = new mmm_t();   
  46.           
  47.         m.mmm_malloc();  
  48.           
  49.         Log.i(TAG,"complexStructTest is test.....");  
  50.           
  51.         /* 赋值 */  
  52.         m.a = 10;  
  53.           
  54.         Log.i(TAG,"complexStructTest 000");  
  55.           
  56.         m.b[0] = 0x22352352;  
  57.         m.b[1] = 0x31212362;  
  58.         m.b[2] = 0x31343521;  
  59.         m.b[3] = 0x33299552;  
  60.           
  61.         Log.i(TAG,"complexStructTest 111");  
  62.         m.c[0].c1 = 0x2352539;  
  63.         Log.i(TAG,"complexStructTest 222");  
  64.         m.c[0].c2 = 0x9235265;  
  65.           
  66.         Log.i(TAG,"complexStructTest 333");  
  67.           
  68.         m.d[0].d1 = 0x983652;  
  69.         String s = "ksdf2035k8";  
  70.         Log.i(TAG,"length111:" + s.length());  
  71.         m.d[0].d2 = s.getBytes();  
  72.           
  73.         m.d[1].d1 = 0x983652;  
  74.         String s1 = "ksdf2035k8";  
  75.         Log.i(TAG,"length222:" + s1.length());  
  76.         m.d[1].d2 = s1.getBytes();  
  77.   
  78.         Log.i(TAG,"complexStructTest 444");  
  79.           
  80.         m.e = 0x8923572;  
  81.           
  82.         Log.i(TAG,"complexStructTest 555");  
  83.           
  84.         /* 设定值到jni层 */  
  85.         int size = 0;  
  86.         size += 4 + 4*4;  
  87.         size += 4*2;  
  88.         size += 2 * (4+64);  
  89.         size += 4 ;  
  90.         Log.i("size","size=" + size);  
  91.           
  92.         int ptr = AllocStructMem(size);  
  93.         Log.i(TAG,"alloc memory address=" + ptr);  
  94.         if(ptr !=0){              
  95.             DSSetInt(ptr,0,m.a);  
  96.               
  97.             DSSetInt(ptr,1,m.b[0]);  
  98.             DSSetInt(ptr,2,m.b[1]);  
  99.             DSSetInt(ptr,3,m.b[2]);  
  100.             DSSetInt(ptr,4,m.b[3]);  
  101.               
  102.             DSSetInt(ptr,5,m.c[0].c1);  
  103.             DSSetInt(ptr,6,m.c[0].c1);  
  104.               
  105.             DSSetInt(ptr,7,m.d[0].d1);  
  106.             DSSetBytes(ptr,8,s.length(),s.getBytes());  
  107.               
  108.             Log.e(TAG,"complexStructTest aaaa");  
  109.             DSSetInt(ptr,12,m.d[1].d1);  
  110.             Log.e(TAG,"complexStructTest bbbb");  
  111.             DSSetBytes(ptr,13,s1.length(),s1.getBytes());  
  112.             Log.e(TAG,"complexStructTest cccc");  
  113.               
  114.             DSSetInt(ptr,17,m.e);  
  115.         }  
  116.           
  117.         if(ptr != 0){  
  118.             FreeStructMem(ptr);  
  119.             ptr = 0;  
  120.         }  
  121.           
  122.         return 0;  
  123.     }</span>  

下面贴下jni实现代码:
[cpp] view plain copy print?
  1. <span style="font-size:16px;">static jint native_setInt(JNIEnv *e, jclass cls, jint addr,jint off,jint len,jint value) {  
  2.     int *ptr = (int*)addr;  
  3.     if(ptr == NULL){  
  4.         LOGE("setInt illegal memory address");  
  5.         return -1;  
  6.     }  
  7.   
  8.     assert( len == 4);  
  9.   
  10.     LOGI("ptr=0x%x,offset=%d native_setInt value = %d",ptr,off,value);  
  11.       
  12.     (*(int*)(ptr + off)) = value;  
  13.     return 0;  
  14. }  
  15.   
  16. static jint native_setBytes(JNIEnv *e, jclass cls, jint addr, jint off, jint len, jbyteArray byteValues) {  
  17.     jbyte *ptr = (jbyte*)addr;  
  18.       
  19.     e->GetByteArrayRegion(byteValues,0,len,ptr+off*4);  
  20.     if(buf == NULL){  
  21.         LOGE("setBytes illegal memory address");  
  22.         return -1;  
  23.     }  
  24.   
  25.     return 0;  
  26. }  
  27.   
  28. static jint native_getInt(JNIEnv *e, jclass cls, jint addr, jint off, jint len) {  
  29.     int value = 0x00;  
  30.     int *ptr = (int*)addr;  
  31.   
  32.     if(ptr == NULL){  
  33.         LOGE("getInt illegal memory address");  
  34.         return -1;  
  35.     }  
  36.   
  37.     assert(len == 4);  
  38.   
  39.     value = *((int*)(ptr + off));  
  40.   
  41.     LOGI("ptr=0x%x,offset=%d native_getInt value = %d",ptr,off,value);  
  42.   
  43.     return value;  
  44. }  
  45.   
  46. static jint native_getBytes(JNIEnv *e, jclass cls, jint addr, jint off, jint len, jbyteArray byteValues) {  
  47.     jbyte *ptr = (jbyte*)addr;  
  48.   
  49.     if(ptr == NULL){  
  50.         LOGE("getBytes illegal memory address");  
  51.         return -1;  
  52.     }  
  53.   
  54.     e->SetByteArrayRegion(byteValues,0,len,ptr+off*4);  
  55.     return 0;  
  56. }  
  57.   
  58. static jint native_alloc(JNIEnv *e, jobject thiz, jint len) {  
  59.     void *ptr = (void*)calloc(1,len);  
  60.     if(ptr == NULL){  
  61.         LOGE("alloc buffer out of memory(size=0x%x)",len);  
  62.         return -1;  
  63.     }  
  64.     return (jint)ptr;  
  65. }  
  66.   
  67. static void native_free(JNIEnv *e, jobject thiz, jint ptr) {  
  68.     if(ptr != NULL){  
  69.         free((void*)ptr);  
  70.         ptr = NULL;  
  71.     }  
  72.     return ;  
  73. }</span>  

嘿嘿,还是够复杂噻,不过比第一个方案前进了一大步。还有没有更好的办法呢?
请听下会分解。。。哈哈哈!!!

0 0
原创粉丝点击