2017-02-04 28 views
6

Tôi cố gắng gọi một ** ngắn bằng C với JNA.Mảng hai chiều JNA

C trông như thế này:

void compute(short** in, int row, int col) { 
    for (int i = 0; i < row; i++) { 
     for (int j = 0; j < col; j++) { 
      printf("in[%d][%d] = %d\n", i,j, in[i][j]); 
     } 
    } 
} 
  • Đi qua một đoạn ngắn [] [] từ JNA không hoạt động.

  • Tài liệu JNA nói "Để ánh xạ mảng đa chiều gốc, hãy sử dụng mảng Java một chiều" nhưng nó không hoạt động. Khi gọi

    'nativeLib.compute (mới ngắn [] {1, 2, 3, 4}, 2, 2); tôi nhận được: java.lang.Error: Truy cập bộ nhớ không hợp lệ tại com.sun.jna.Native.invokeVoid (Native Method)

  • Dường như một PointerByReference là cần thiết, tôi đã cố gắng để lấp đầy PointerByReference với PointerByReference có chứa giá trị ngắn nhưng nó không hoạt động:

    Pointer pointerOfArray = new Memory(row * col * Native.getNativeSize(Short.TYPE)); 
    for(int i=0;i<row;i++) { 
    
        Pointer pointer = new Memory(col * Native.getNativeSize(Short.TYPE)); 
        for(int j=0;j<col;j++) { 
         pointer.setShort(j*Native.getNativeSize(Short.TYPE), in[i][j]); 
        } 
        pointerOfArray.setPointer(i*row*Native.getNativeSize(Short.TYPE), pointer); 
    } 
    
  • tôi cũng đã cố gắng:

    Pointer pointer = new Memory(4*Short.SIZE); 
    
    Pointer pointer1 = new Memory(2*Short.SIZE); 
    pointer1.setShort(0,(short)1); 
    pointer1.setShort(Short.SIZE,(short)2); 
    
    Pointer pointer2 = new Memory(2*Short.SIZE); 
    pointer2.setShort(0,(short)3); 
    pointer2.setShort(Short.SIZE,(short)4); 
    
    pointer.setPointer(0, pointer1); 
    pointer.setPointer(2*Short.SIZE, pointer2); 
    
    nativeLib.compute(new PointerByReference(pointer), 2,2); 
    

nhưng tôi nhận được in[0][0] = 3184 in[0][1] = 10460 in[1][0] = 3344 in[1][1] = 10460

Có ai có ý tưởng không? Tôi không thể thay đổi chữ ký C, tôi phải giải quyết vấn đề này ngắn **

Cảm ơn rất nhiều.

Giải pháp

tôi finnaly succed! làm điều này:

 short[][] in = { 
      {1,2,3}, 
      {4,5,6}, 
    }; 

    Pointer[] data = new Pointer[in.length]; 
    for(int i=0;i<in.length;i++) { 
     data[i] = new Memory(2*Short.SIZE); 
     data[i].write(0, in[i], 0,in[0].length); 
    } 

    nativeLib.compute(data, in.length,in[0].length); 

Với kết quả:

in[0][0] = 1 
in[0][1] = 2 
in[0][2] = 3 
in[1][0] = 4 
in[1][1] = 5 
in[1][2] = 6 

Cảm ơn rất nhiều!

+0

Vui mừng khi thấy phiên bản "mảng con trỏ" đã hoạt động cho bạn! –

Trả lời

2

JNA chỉ xử lý các mảng thứ nguyên duy nhất.

Và về mặt kỹ thuật, C. A short * có thể là mảng 1d, 2d hoặc 3d. Bạn sẽ không biết trừ khi bạn biết bên trong. Chỉ bằng cách đọc tài liệu, bạn có biết rằng hàm đang mong đợi một mảng 2D. Tất cả những gì bạn thực sự làm là chuyển một con trỏ tới phần tử đầu tiên của mảng (tổng chiều dài hàng * col), và sau đó sử dụng (rowIndex * col + colIndex) để tìm nạp kết quả. Trong JNA bạn chỉ cần sử dụng một mảng 1D để phù hợp.

Trong trường hợp này, tuy nhiên, bạn có short ** để bạn biết mình có một mảng con trỏ 1D, mỗi con trỏ trỏ đến mảng 1D là short s. Trong JNA, bạn tạo một mảng con trỏ (Pointer[]) cho lần đầu tiên *; mỗi điểm sẽ trỏ đến cột "đầu tiên" đầu tiên của hàng mới (thứ hai *).

Lỗi Invalid Memory Access cho biết bạn đã không cấp phát bộ nhớ gốc đúng cách và cung cấp cho bạn gợi ý rõ ràng về câu trả lời: bạn không thể chuyển mảng nguyên thủy làm tham số. Bạn phải cấp phát bộ nhớ của mình, bằng cách sử dụng lớp Memory hoặc bằng cách bao gồm mảng như một phần của một Structure.

new short[] {1, 2, 3, 4} không hoạt động ở đây, vì bạn chưa cấp bộ nhớ gốc để hỗ trợ bộ nhớ java cho mảng đó. Bạn đã đi đúng hướng với việc cấp phát bộ nhớ mà bạn đã thực hiện bằng cách sử dụng lớp Memory.

Trong C, short** in đang mong đợi một mảng con trỏ. Vì vậy, bạn nên bắt đầu ra bằng cách tuyên bố một mảng của con trỏ:

Pointer[] p = new Pointer[row]; 

Sau đó, bạn sẽ đặt con trỏ cho mỗi hàng, phân bổ bộ nhớ:

p[0] = new Memory(col * Native.getNativeSize(Short.TYPE)); 
p[1] = new Memory(col * Native.getNativeSize(Short.TYPE)); 

Bây giờ, bạn có thể viết giá trị mảng của bạn. Bạn có thể duyệt qua các cột với offset và setShort() nhưng bạn cũng có thể viết trực tiếp sử dụng Pointer.write() ví dụ

p[0].write(0, new short[] {1, 2}, 0, 2); 
p[1].write(0, new short[] {3, 4}, 0, 2); 

Sau đó, bạn sẽ vượt qua p vào thư mục C có nguồn gốc cho in.

+0

Về giải pháp đầu tiên, gọi 'nativeLib.compute (new short [] {1, 2, 3, 4}, 2, 2);' đưa ra một ; "Ngoại lệ trong chuỗi" chính "java.lang.Error: Truy cập bộ nhớ không hợp lệ \t tại com.sun.jna.Native.invokeVoid (Phương pháp gốc)" –

+0

Tôi đã cập nhật câu trả lời của mình ... –

+0

Cảm ơn rất nhiều sự giúp đỡ của bạn đó là almose ok, nhưng với cả hai giải pháp cập nhật kết quả là: 'trong [0] [0] = 1 trong [0] [1] = 2 trong [1] [0] = 3200 trong [1] [1] ] = 10525' –

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