2016-03-22 15 views
5

Tôi bắt đầu sử dụng JNA để giao tiếp với một thiết bị trên giao diện RS485 của máy tính. Ngạc nhiên với tôi, tôi đã có kết quả tốt rất nhanh. Nhưng bây giờ tôi bị mắc kẹt bởi một vấn đề đơn giản. Thư viện tôi sử dụng chấp nhận một con trỏ đến một con trỏ của struct. Chữ ký thực tế làJNA: Đặt con trỏ cấu trúc thành NULL

func(Struct1 **, Struct2 **, Struct3 *, Struct4 *, long)

Bây giờ để biết kích thước của các tham số đầu tiên thư viện hy vọng con trỏ cuối cùng trở thành một con trỏ NULL. Đây là những gì thất bại. Mã sau đây là những gì tôi đã cố gắng cho đến nay:

Struct1.ByReference[] s = (Struct1.ByReference[]) new Struct1.ByReference().toArray(size); 
    int pos = 0; 

    // ... 
    // for loop to set the s[pos] struture values 
    for(pos = 0; pos < size - 1; pos++) 
    // ... 

    // Now set the last array element to a null pointer to indicate end-of-list 
    s[pos].getPointer().setPointer(0, null);// Following does not work: results in zero memoried structure 
    s[pos] = null; // Following does not work wither: NullPointerException at com.sun.jna.Structure.autoWrite 

EDIT 1

s[pos] = new Struct1.ByReference(Pointer.NULL); // results in zero memoried structure as well 

EDIT 2

Theo câu hỏi của technomage. Nếu tôi viết mã C, nó có thể trông giống như thế:

Struct1 **s = malloc(n * sizeof(Struct1*)); 

for(int i=0; i<n; i++) 
{ 
    if(i == n -1) 
    { 
     s[i] = NULL; 
    } 
    else 
    { 
     s[i] = malloc(sizeof(Struct1)); 
     s[i].bla = value; 
     .... 
    } 
} 

Nhưng được cảnh báo: Tôi không giỏi về C/C++. Tôi coi Java là miền của tôi.

Có ai có vấn đề tương tự không? Có lẽ tôi chỉ không thấy gỗ cho cây cối ...

Xin cảm ơn trước.

+0

Vui lòng bao gồm mẫu sử dụng gốc. Các khai báo hàm cho các biến thể con trỏ có thể không rõ ràng nếu không có ngữ cảnh đó - không có cách nào để phân biệt giữa một con trỏ với một mảng, một con trỏ tới một giá trị con trỏ đơn lẻ hoặc một vài biến thể khác. – technomage

+0

Bạn có ý nghĩa gì với 'sử dụng ví dụ'? Thư viện được sử dụng từ mã của một thiết bị nhúng chạy FreeRTOS, một hệ điều hành thời gian thực nguồn mở. Tôi không có bất kỳ mã gốc nào ngoài tệp tiêu đề xuất các phương thức của thư viện. –

+0

Nếu bạn đã viết mã trong 'C' để truy cập thư viện theo cách bạn muốn, điều gì sẽ _that_ trông như thế nào? – technomage

Trả lời

0

Cấu trúc trong JNA là con trỏ, vì vậy những gì bạn thực sự cần ở đây là con trỏ đến cấu trúc (con trỏ đến a), là PointerByReference - trong trường hợp của bạn, một mảng trong số đó.

Với mã ví dụ trên, bạn sẽ tạo mảng của bạn của Kiến trúc, một ít hơn n:

Struct1[] struct1Array = new Struct1[n-1]; 

này chỉ phân bổ bộ nhớ Java cho mảng.

Tiếp theo bạn sẽ nhanh chóng và viết những thay đổi bạn thực hiện cho bộ nhớ quê hương:

for (int i = 0; i < n-1; i++) { 
    struct1Array[i] = new Struct1(); 
    struct1Array[i].bla = value; 
    struct1Array[i].write(); 
} 

Các new Struct1() cấp phát bộ nhớ bên mẹ đẻ cho các công trình. Có thể sử dụng phương thức Structure.toArray() để thực hiện việc này; Tôi cố tình làm điều này một chút hướng dẫn sử dụng và mức độ thấp để cố gắng làm rõ những gì đang xảy ra.

Sau đó, bạn sẽ tạo một mảng PointerByReference tương ứng để giữ các con trỏ đến các cấu trúc này. Bạn sẽ thêm phần tử bổ sung cho ô trống:

PointerByReference[] pbrArray = new PointerByReference[n]; 

Một lần nữa, đây chỉ là phân bổ bên java. Và sau đó bạn điền vào nó với con trỏ đến con trỏ đến cấu trúc, thu được từ Structure.getPointer() phương pháp:

for (int i = 0; i < n-1; i++) { 
    pbrArray[i] = new PointerByReference(struct1Array[i].getPointer()); 
} 
pbrArray[n - 1] = new PointerByReference(Pointer.NULL); 

Các new PointerByReference() đây phân bổ bộ nhớ bên mẹ đẻ cho con trỏ chính nó, mà chỉ vào cấu trúc bản địa phía bạn phân bổ sớm hơn.

Từ cách tôi hiểu câu hỏi ban đầu của bạn, bạn sẽ chuyển mảng PointerByReference này cho hàm của mình, có lẽ là cập nhật cấu trúc của bạn.

Vì bạn đã tạo hai mảng theo cách này, bạn có thể theo dõi sự tương ứng của chúng theo chỉ mục mảng. Bạn có thể phải lặp qua mảng cấu trúc và read() bộ nhớ riêng vào cấu trúc phía Java để xử lý thêm với nó. Thông thường khi bạn làm việc trực tiếp với các cấu trúc được truyền cho các phương thức mà họ tự động viết và autoread, nhưng khi sử dụng PointerByReference để tham chiếu gián tiếp Cấu trúc, JNA không thân thiện. Để thay thế cho việc theo dõi hai mảng bằng các chỉ mục tương ứng, bạn có thể "quên" việc gán Cấu trúc ban đầu và khôi phục nó sau này bằng phương pháp PointerByReference.getValue() trên mảng của bạn để khôi phục con trỏ tới bộ nhớ cho cấu trúc, và sau đó khởi tạo một cấu trúc mới sử dụng Con trỏ đó trong hàm tạo của nó (ví dụ: new Struct1(pbr.getValue()) gọi là super() với con trỏ đó).

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