2012-03-01 37 views
11

Mục tiêu của tôi là chuyển một mảng byte có độ dài biến đổi từ mã gốc sang phía Java. Java phương pháp lớp dụ mất bytearray như là đối số của nó:Truyền mảng byte từ mã gốc sang phía Java

private void writeBuffer(final byte[] buffer) 
{ 
} 

Tôi có thể tìm thấy một ID phương pháp trong mã nguồn gốc:

jclass cls = (*env)->FindClass(env,"class_path"); 
jmethodID writeBufferMethodID = (*env)->GetMethodID(env, cls, "writeBuffer", "([B)V"); 

Nhưng vẫn không thể tìm ra cách để vượt qua một byte mảng đúng. Tôi đã thử:

jbyteArray retArray = (*env)->NewByteArray(env, data_size); 
void *temp = (*env)->GetPrimitiveArrayCritical(env, (jarray)retArray, 0); 
memcpy(temp, decoded_frame->data[0], data_size); 
(*env)->CallVoidMethod(env, obj, writeBufferMethodID, retArray); 
(*env)->ReleasePrimitiveArrayCritical(env, retArray, temp, 0); 

và cũng:

retArray = (*env)->NewByteArray(env, data_size); 
(*env)->SetByteArrayRegion(env, retArray, 0, data_size, (jbyte *)decoded_frame->data[0]); 
(*env)->CallVoidMethod(env, obj, writeBufferMethodID, retArray); 

Phương pháp Java được gọi, nhưng sau một thời gian các ứng dụng bị treo. Hơn nữa, tất cả các giá trị trong bộ đệm Java tôi nhận được bằng không vì vậy có vẻ như nội dung không được sao chép cả.

Tôi đã xác minh nội dung bộ đệm (decoded_frame-> data [0]) ở phía gốc bằng cách ghi chúng vào tệp nhị phân và không có vấn đề gì, tệp chứa chính xác những gì tôi mong đợi.

Tôi gọi phương thức đó theo định kỳ; kích thước của mảng có thể thay đổi trong mỗi cuộc gọi.

Chính xác và hầu hết hiệu quả cách là gì? Phân bổ một mảng mới trong mỗi cuộc gọi rõ ràng là một ý tưởng ngớ ngẩn, nhưng tôi không biết, làm thế nào để tránh điều đó nếu kích thước mảng thay đổi.

EDIT:

Tôi đã viết lại mã của tôi theo cách này và nó có vẻ là OK bây giờ.

gọi trong một vòng lặp while:

... làm một số giải mã ...

if(!retArray) 
retArray = (*env)->NewByteArray(env, data_size); 

if((*env)->GetArrayLength(env, retArray) != data_size) 
{ 
(*env)->DeleteLocalRef(env, retArray); 
retArray = (*env)->NewByteArray(env, data_size); 
} 

void *temp = (*env)->GetPrimitiveArrayCritical(env, (jarray)retArray, 0); 
memcpy(temp, decoded_frame->data[0], data_size); 
(*env)->CallVoidMethod(env, obj, writeBufferMethodID, retArray); 
(*env)->ReleasePrimitiveArrayCritical(env, retArray, temp, 0); 

gọi tại lối ra loop:

(*env)->DeleteLocalRef(env, retArray); 

Trả lời

5

Thử gọi ReleasePrimitiveArrayCritical trước khi bạn gọi CallVoidMethod.

+0

Tôi đã thử nhưng không có gì thay đổi. Sau một thời gian, tôi nhận thấy lỗi JVM: 'Không thêm vào bảng ref địa phương JNI (có 512 mục)' đã chỉ cho tôi vấn đề với việc xóa tham chiếu cục bộ của 'retArray'. Tôi đã viết lại mã của tôi - xem phần chỉnh sửa trong câu hỏi. Bây giờ nó vượt qua mảng một cách chính xác, nhưng một vấn đề khác xảy ra ở phía Java - không nằm trong phạm vi của câu hỏi này. – vitakot

+3

Vẫn còn sai khi gọi phương thức jni sau GetPrimitiveArrayCritical và trước ReleasePrimitveArrayCritical. Đọc tại đây: http://java.sun.com/docs/books/jni/html/functions.html#64717 (tìm kiếm GetPrimitiveArrayCritical) –

+0

Có, bạn nói đúng, cảm ơn! Đã bỏ phiếu, nhưng không thể chấp nhận câu trả lời vì nó không phải là nguồn lỗi - trong trường hợp của tôi. – vitakot

3

Dưới đây ví dụ về các công việc để chuyển char [] từ mã C sang byte Java [].

void JNICALL Java_com_example_testapplication_MainActivity_getJNIByteArrayArg(JNIEnv *jenv, jobject jobj) 
{ 
jclass clazz = (*jenv)->FindClass(jenv, "com/example/testapplication/MainActivity"); // class path 
jmethodID mid = (*jenv)->GetMethodID(jenv, clazz, "addData", "([B)V");// function name 

jbyteArray retArray; 
char data[] = {'a','b',3,4,5}; 
int data_size = 5; 
if(!retArray) 
retArray = (*jenv)->NewByteArray(jenv, data_size); 

if((*jenv)->GetArrayLength(jenv, retArray) != data_size) 
{ 
    (*jenv)->DeleteLocalRef(jenv, retArray); 
    retArray = (*jenv)->NewByteArray(jenv, data_size); 
} 

void *temp = (*jenv)->GetPrimitiveArrayCritical(jenv, (jarray)retArray, 0); 
memcpy(temp, data, data_size); 
(*jenv)->ReleasePrimitiveArrayCritical(jenv, retArray, temp, 0); 

(*jenv)->CallVoidMethod(jenv, jobj, mid, retArray); 
} 
public void addData(byte[] data) { 
System.out.println("Buyya: From C: " + new String(data)); 
}