2009-08-05 28 views
5

Tôi đã đăng câu hỏi liên quan đến nó, nhưng tại thời điểm đó tôi chưa có tài khoản. Tôi có một câu trả lời nhưng tôi vẫn còn bối rối và tôi không thể tiếp tục chủ đề đó.Lấy mảng byte có chiều dài không xác định từ cửa hàng Java

Tôi đang đăng lại câu hỏi cùng với liên kết tới cuộc hội thoại trước đó.

Returning char array from java to string - JNI

Dữ liệu tôi lưu trữ trong Java được đăng. Tôi thực hiện cuộc gọi hàm java bằng cách sử dụng đoạn mã sau.

Mã sau giả định rằng char của C tương thích với byte của Java, vì char của Java là 2 byte trong khi char của C là 1 byte. Các jbyte cũng là một char ký *

//value will be the serialized data 
void store(char* key, char* value, int val_len) 

{

//consider the jclass and methodid are already initialized 

    jstring j_key = (*env)->NewStringUTF(env, key); 
    jbyteArray j_value = (*env)->NewByteArray(env, val_len); 

    (*env)->SetByteArrayRegion(env, j_value, 0, val_len, (jbyte *)value); 

    //The store method on java side will save the value (as is) in memory 
    (*env)->CallStaticVoidMethod(j_class, store_method, key, value); 

    (*env)->ReleaseByteArrayElements(env, j_value, (jbyte *)value, JNI_ABORT); 
    (*env)->ReleaseStringUTFChars(env, j_key, key); 

}

Một khi tôi đã lưu dữ liệu, tôi sử dụng chức năng khác để lấy dữ liệu từ cửa hàng. Tại thời điểm đó tôi không biết kích thước của dữ liệu tôi sẽ lấy. API của tôi là trong C và lưu trữ là trong Java. Tôi sẽ sử dụng các hàm C của mình để tương tác với Java. Và cũng có thể có nhiều luồng truy xuất dữ liệu từ cửa hàng Java cùng một lúc.

Tôi đang thực hiện cuộc gọi từ C đến Java và điều khiển của tôi sẽ trở lại chương trình C sau khi truy xuất dữ liệu. Tôi là một chút nhầm lẫn về cách mã sẽ hoạt động. Làm thế nào tôi sẽ nhận được con trỏ đến mảng (lấy từ java) và sau đó lấy nó bằng cách sử dụng GetByteArrayElements. Hãy nhớ rằng tôi không biết kích thước của dữ liệu tôi sẽ lấy trước khi bàn tay và do đó không thể tạo ra một mảng byte bằng cách sử dụng chức năng NewByteArray và sau đó điền nó với dữ liệu trong mã java.

Trả lời

12

Ok, tôi đã hiểu nó. Tôi sẽ đặt nó xuống đây để những người khác cũng có thể tận dụng nó.

Xem xét các phương pháp java sau đó trả về một mảng byte (chỉ cần một mã giả, không có kiểm tra vv)

public static byte[] GetData(){ 
    return myStore.getData(); 
} 

và đứng về phía C, bạn có thể lấy các byte [] như sau

void get_data() 
{  
    int len = 0; 
    char* value = NULL; 
    /*Consider j_class, and j_methodid are already initialized*/ 
    jbyteArray j_value = (*env)->CallStaticObjectMethod(env, j_class, j_methodid); 

    if(j_value != NULL) 
    { 
     len = (*env)->GetArrayLength(env, j_value); 
     value = (*env)->GetByteArrayElements(env, j_value, NULL); 
    } 

    /*later on release the resource*/ 
    (*env)->ReleaseByteArrayElements(env, j_value, value, 0); 
} 

Tôi đã kiểm tra và nó hoạt động. Tôi sẽ kiểm tra nó cho mảng 2-D bây giờ. Tôi nghĩ rằng nó sẽ được giống như điều này chỉ bạn sẽ nhận được jobjectArray và mọi yếu tố của mảng này là một jbyteArray.

+0

Cảm ơn tôi đã gặp sự cố tương tự và mã này hữu ích. Trong VisualStudio tôi đã bao gồm một số phôi để có được nó để biên dịch mặc dù, tôi đã phải trả giá trị trả lại từ CallStaticObjectMethod với (jbyteArray), và tôi đã phải trả giá trị trả về từ GetByteArrayElements với (char *) –

+0

Cảm ơn bạn cho điều này! 4 năm sau, tôi đã gặp vấn đề tương tự trong các phương thức env-> không hoạt động để đọc trong một mảng mảng byte. Giải pháp này làm việc :) – blkhatpersian

1

Cảm ơn bạn rất nhiều! Tôi đã cố gắng để vượt qua một mảng đôi từ C đến Java và java lần lượt trả về một mảng đôi mới để C. Đây là một phần của JNI nơi tôi đang cố gắng liên kết một mã Java để mã nguồn Fortran. Nhưng mã Fortran phải gọi thêm một mã Java để tính toán. Vì vậy, tôi đang làm Java để C để Fortran để C để Java bằng cách sử dụng JNI. Giải pháp để gửi một mảng kép từ C đến Java và Java trả về một mảng kép cho C là ở đây.

jdoubleArray tempA = (jdoubleArray)(*envG)->NewDoubleArray(envG,3); //create an array with 3 elements to be sent to Java 
jdoubleArray tempB = (jdoubleArray)(*envG)->NewDoubleArray(envG,3); //This is will be //assigned to returned java double array 
(*envG)->SetDoubleArrayRegion(envG,tempA,0,3,(const jdouble *)arr);//need to send the //tempA array to Java. "arr" is the double array coming to C from Fortran! 
int leng = 0; 
for (i = 0; i < 1; i++) { 
//sending an array "tempA" to Java. Java returns tempB, a double array 
tempB = (*envG)->CallObjectMethod(envG, obj_print, id_print,(*A),(*B),(*C),tempA); 
    if (tempB != NULL){ 
    for (k = 0; k < 3; k++){ 
     leng = (*envG)->GetArrayLength(envG, tempB); 
    jdouble* value = (*envG)->GetDoubleArrayElements(envG, tempB, NULL); 
     printf("FROM JAVA ARRAY %f\n", value[k]); 
    } //end for 
    } //end if 
+0

Cảm ơn.Hy vọng nó sẽ giúp người khác – ata

Các vấn đề liên quan