2011-09-16 37 views
5

Tôi có một hàm C như thế này:trả lại một mảng từ C đến Java với SWIG

void get_data(const obj_t *obj, short const **data, int *data_len); 

tôi đã viết nó như thế này đặc biệt cho Uống một lân, vì

const short *get_data(const obj_t *obj, int *data_len); 

nguyên nhân gặp khó khăn, như typemaps SWIG của không đủ thông minh để kết hợp data_len với giá trị trả lại.

Trong Java Tôi muốn để có thể gọi hàm này như sau:

short data[]= mylib.get_data(obj); 

Nhưng tôi không thể tìm ra cách để có được những tham số đầu ra mảng để trở thành một giá trị trả về. Với Ruby và Python, nó hoạt động tốt, vì SWIG cho các ngôn ngữ đó hỗ trợ các tham số đầu ra trả về dưới dạng các giá trị trả về (vì các ngôn ngữ có thể có nhiều giá trị trả lại).

Tôi làm cách nào để làm việc này với Java?

+0

Bạn vẫn đang tìm kiếm một giải pháp cho điều này? – Flexo

+0

vâng tôi vẫn không biết cách làm điều này – paleozogt

+0

Tôi đã trả lời bằng một câu trả lời khớp chính xác với cú pháp Java mà bạn đã yêu cầu. Có một cách có thể để trả lời với hàm C ban đầu, nếu bạn có thể truy vấn kích thước mà không làm đầy mảng. Tôi sẽ thêm điều đó vào câu trả lời của tôi nếu bạn quan tâm. – Flexo

Trả lời

7

tôi đã tổng hợp các tập tin tiêu đề kiểm tra sau đây để chứng minh vấn đề:

typedef struct { } obj_t; 

const short *get_data(const obj_t *obj, int *data_len) { 
    (void)obj; 
    static short arr[] = {1,2,3,4,5}; 
    *data_len = sizeof(arr)/sizeof(*arr); 
    return arr; 
} 

Tôi sẽ nói chuyện thông qua các tập tin mô-đun tôi đã viết, nó bắt đầu khá chuẩn:

%module test 

%{ 
#include "test.h" 
%} 

Sau đó, chúng tôi thiết lập một typemap cho đối số data_len. Nó không cần hiển thị ở phía Java vì độ dài sẽ được mảng biết, nhưng chúng ta cần sắp xếp một số lưu trữ cho con trỏ trỏ tới và chúng ta đảm bảo nó kéo dài đủ để chúng ta có thể đọc nó sau khi cũng trả về mảng cho Java.

%typemap(in,numinputs=0,noblock=1) int *data_len { 
    int temp_len; 
    $1 = &temp_len; 
} 

Sau đó, chúng tôi muốn SWIG sử dụng short[] ở phía bên Java cho các kiểu trả về:

%typemap(jstype) const short *get_data "short[]" 
%typemap(jtype) const short *get_data "short[]" 

jshortArray ở phía JNI - không cần phải xây dựng một loại proxy, vì vậy chúng tôi chỉ cần vượt qua giá trị trả lại trực tiếp thông qua:

%typemap(jni) const short *get_data "jshortArray" 
%typemap(javaout) const short *get_data { 
    return $jnicall; 
} 

Cuối cùng, chúng tôi tạo ra một typemap sẽ tạo mảng mới, với kích thước dựa trên độ dài được trả về từ niềm vui ction và sao chép kết quả trả về vào mảng Java cho chúng ta. Nếu cần chúng ta nên free() mảng kết quả thực sự ở đây, nhưng trong ví dụ của tôi nó được phân bổ tĩnh nên không cần phải được giải phóng.

%typemap(out) const short *get_data { 
    $result = JCALL1(NewShortArray, jenv, temp_len); 
    JCALL4(SetShortArrayRegion, jenv, $result, 0, temp_len, $1); 
    // If the result was malloc()'d free it here 
} 

Cuối cùng chúng tôi bao gồm các tập tin tiêu đề cho SWIG để bọc, bằng cách sử dụng typemaps chúng tôi chỉ viết:

%include "test.h" 

Tôi đã thử nghiệm này với:

public class run { 
    public static void main(String argv[]) { 
    System.loadLibrary("test"); 
    obj_t obj = new obj_t(); 
    short[] result = test.get_data(obj); 
    for (int i = 0; i < result.length; ++i) { 
     System.out.println(result[i]); 
    } 
    } 
} 

nào sản xuất:

 
1 
2 
3 
4 
5 

Để tham khảo bạn có thể quấn:

void get_data(const obj_t *obj, short const **data, int *data_len); 

cũng mặc dù nếu chức năng của bạn đã có một cách để truy vấn kích thước mà không cần thiết lập mảng bạn có thể bọc này hơi thông minh hơn bằng cách phân bổ một mảng của các kích thước chính xác trên Java bên. Để làm điều này, bạn muốn viết một hàm trung gian trong Java để truy vấn kích thước, thiết lập cuộc gọi và sau đó trả về mảng kết quả. Điều này sẽ cho phép bạn sử dụng GetShortArrayElements/ReleaseShortArrayElements cho cuộc gọi có khả năng 0 bản sao.

này sẽ làm việc vì mảng trong Java được về cơ bản thông qua tham khảo, ví dụ .:

public class ret { 
    public static void foo(int arr[]) { 
    arr[0] = -100; 
    } 

    public static void main(String argv[]) { 
    int arr[] = new int[10]; 
    System.out.println(arr[0]); 
    foo(arr); 
    System.out.println(arr[0]); 
    } 
} 
+2

Để thuận tiện, tệp giao diện hoàn chỉnh mà tôi đã sử dụng để kiểm tra có trên trang web của tôi tại: http://static.lislan.org.uk/~ajw/javaarrout.i - nếu liên kết đó bị ngắt, câu trả lời sẽ không mất gì vì nó có thể sao chép từ chính câu trả lời. – Flexo

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