确认让人很头痛噻!
问题解决方案2:
重点就是利用C++层分配共享内存空间,函数参数非常简单,只需要返回值,所有参数传递利用共享内存搞定
这利方式对于参数的传递非常方便,只是需要注意地址及偏移值(addr:offset),代码比较清晰。
但对于native函数及jmethodID与jfieldID的处理还是很麻烦呀!不对对于参数处理简化了很多了。
基本代码如下,我这里搞了个最复杂的传递结构参数举例:
JAVA 代码编写如下
/**
* 按长度进行缓冲区分配空间
* @param length: buffer length
* @return start address
*/
public int AllocStructMem(int length){
if (length % 4 != 0) {
length -= (length % 4);
length += 4;
}
if ((address = native_alloc(length)) == 0)
throw new RuntimeException();
return address;
}
/**
* 释放缓冲区空间
* @param ptr:start address
*/
public void FreeStructMem(int ptr){
if(ptr == 0x00){
throw new NullPointerException("NULL pointer");
}
native_free(ptr);
}
public int DSSetInt(int ptr,int offset,int value) {
if(ptr == 0x00){
throw new NullPointerException("NULL pointer");
}
return native_setInt(ptr,offset,4,value);
}
public int DSSetBytes(int addr,int off,int len,byte[] b){
return native_setBytes(addr,off, len, b);
}
public void DSSetUTFString(int addr,int off, int len, String s) {
DSSetBytes(addr,off, len, s.getBytes());
}
public int DSGetInt(int addr,int off, int len) {
if(off < 0 || len <= 0 || addr == 0x00 )
throw new IllegalArgumentException();
return native_getInt(addr, off, len);
}
public int DSGetBytes(int addr,int off, int len, byte[] b) {
if (off < 0 || len <= 0 || addr == 0x00 ||b == null || b.length < len)
throw new IllegalArgumentException();
return native_getBytes(addr, off, len, b);
}
public String DSGetUTFString(int addr,int off, int len) {
if (off < 0 || len <= 0 )
throw new IllegalArgumentException();
byte[] b = new byte[len];
native_getBytes(addr, off, len, b);
return new String(b);
}
private static native int native_alloc(int length);
private static native void native_free(int ptr);
private static native int native_setInt(int addr, int offset, int len,
int value);
private static native int native_setBytes(int addr, int offset, int len,
byte[] b);
private static native int native_getInt(int addr, int offset, int len);
private static native int native_getBytes(int addr, int offset, int len,
byte[] b);
下面是测试代码:
// C++ 定义结构
// struct mmm_t {
// int a;
// int b[4];
// struct {
// int c1, c2;
// } c;
// struct {
// int d1;
// char*d2;
// } d[2];
// float e;
// };
static class cc{
int c1;
int c2;
}
static class dd{
int d1;
byte[] d2 = new byte[64];
};
static class mmm_t{
int a;
int[] b = new int[4];
cc c[] = new cc[1];
dd d[] = new dd[2];
int e;
dd darr[] = new dd[10];
public void mmm_malloc(){
c[0] = new cc();
for(int i=0;i<2;i++){
d[i] = new dd();
}
for(int i=0; i < 10; i++){
darr[i] = new dd();
}
}
}
public int complexStructTest(){
mmm_t m = new mmm_t();
m.mmm_malloc();
Log.i(TAG,"complexStructTest is test.....");
/* 赋值 */
m.a = 10;
Log.i(TAG,"complexStructTest 000");
m.b[0] = 0x22352352;
m.b[1] = 0x31212362;
m.b[2] = 0x31343521;
m.b[3] = 0x33299552;
Log.i(TAG,"complexStructTest 111");
m.c[0].c1 = 0x2352539;
Log.i(TAG,"complexStructTest 222");
m.c[0].c2 = 0x9235265;
Log.i(TAG,"complexStructTest 333");
m.d[0].d1 = 0x983652;
String s = "ksdf2035k8";
Log.i(TAG,"length111:" + s.length());
m.d[0].d2 = s.getBytes();
m.d[1].d1 = 0x983652;
String s1 = "ksdf2035k8";
Log.i(TAG,"length222:" + s1.length());
m.d[1].d2 = s1.getBytes();
Log.i(TAG,"complexStructTest 444");
m.e = 0x8923572;
Log.i(TAG,"complexStructTest 555");
/* 设定值到jni层 */
int size = 0;
size += 4 + 4*4;
size += 4*2;
size += 2 * (4+64);
size += 4 ;
Log.i("size","size=" + size);
int ptr = AllocStructMem(size);
Log.i(TAG,"alloc memory address=" + ptr);
if(ptr !=0){
DSSetInt(ptr,0,m.a);
DSSetInt(ptr,1,m.b[0]);
DSSetInt(ptr,2,m.b[1]);
DSSetInt(ptr,3,m.b[2]);
DSSetInt(ptr,4,m.b[3]);
DSSetInt(ptr,5,m.c[0].c1);
DSSetInt(ptr,6,m.c[0].c1);
DSSetInt(ptr,7,m.d[0].d1);
DSSetBytes(ptr,8,s.length(),s.getBytes());
Log.e(TAG,"complexStructTest aaaa");
DSSetInt(ptr,12,m.d[1].d1);
Log.e(TAG,"complexStructTest bbbb");
DSSetBytes(ptr,13,s1.length(),s1.getBytes());
Log.e(TAG,"complexStructTest cccc");
DSSetInt(ptr,17,m.e);
}
if(ptr != 0){
FreeStructMem(ptr);
ptr = 0;
}
return 0;
}
static jint native_setInt(JNIEnv *e, jclass cls, jint addr,jint off,jint len,jint value) {
int *ptr = (int*)addr;
if(ptr == NULL){
LOGE("setInt illegal memory address");
return -1;
}
assert( len == 4);
LOGI("ptr=0x%x,offset=%d native_setInt value = %d",ptr,off,value);
(*(int*)(ptr + off)) = value;
return 0;
}
static jint native_setBytes(JNIEnv *e, jclass cls, jint addr, jint off, jint len, jbyteArray byteValues) {
jbyte *ptr = (jbyte*)addr;
e->GetByteArrayRegion(byteValues,0,len,ptr+off*4);
if(buf == NULL){
LOGE("setBytes illegal memory address");
return -1;
}
return 0;
}
static jint native_getInt(JNIEnv *e, jclass cls, jint addr, jint off, jint len) {
int value = 0x00;
int *ptr = (int*)addr;
if(ptr == NULL){
LOGE("getInt illegal memory address");
return -1;
}
assert(len == 4);
value = *((int*)(ptr + off));
LOGI("ptr=0x%x,offset=%d native_getInt value = %d",ptr,off,value);
return value;
}
static jint native_getBytes(JNIEnv *e, jclass cls, jint addr, jint off, jint len, jbyteArray byteValues) {
jbyte *ptr = (jbyte*)addr;
if(ptr == NULL){
LOGE("getBytes illegal memory address");
return -1;
}
e->SetByteArrayRegion(byteValues,0,len,ptr+off*4);
return 0;
}
static jint native_alloc(JNIEnv *e, jobject thiz, jint len) {
void *ptr = (void*)calloc(1,len);
if(ptr == NULL){
LOGE("alloc buffer out of memory(size=0x%x)",len);
return -1;
}
return (jint)ptr;
}
static void native_free(JNIEnv *e, jobject thiz, jint ptr) {
if(ptr != NULL){
free((void*)ptr);
ptr = NULL;
}
return ;
}