2009-05-07 32 views
6

tôi có một dự án C# là hàng nhập khẩu một dll C, dll có chức năng này:con trỏ Đi qua từ mã không được quản lý

int primary_read_serial(int handle, int *return_code, int *serial, int length); 

Tôi muốn được tiếp cận với các thông số sê-ri. Tôi đã thực sự có nó để trả lại một ký tự của tham số nối tiếp, nhưng tôi không thực sự chắc chắn những gì tôi đang làm và muốn hiểu những gì đang xảy ra, và tất nhiên làm cho nó hoạt động.

Vì vậy, tôi rất chắc chắn rằng dll đang được truy cập, các chức năng khác không có con trỏ hoạt động tốt. Làm cách nào để xử lý con trỏ? Tôi có phải sắp xếp nó không? Có lẽ tôi phải có một nơi cố định để đưa dữ liệu đó?

Giải thích sẽ tuyệt vời.

Cảm ơn! Richard

Trả lời

8

Bạn sẽ phải sử dụng IntPtr và Marshal mà IntPtr vào bất kỳ cấu trúc C# nào bạn muốn đặt. Trong trường hợp của bạn, bạn sẽ phải sắp xếp nó thành int [].

này được thực hiện theo nhiều bước sau:

  • Phân bổ một tay cầm không được quản lý
  • Gọi chức năng với các mảng unamanged
  • Chuyển đổi mảng để mảng byte quản lý
  • Chuyển đổi byte mảng int array
  • Thao tác không được quản lý bản phát hành

Mã đó sẽ cung cấp cho bạn ý tưởng:

// The import declaration 
[DllImport("Library.dll")] 
public static extern int primary_read_serial(int, ref int, IntPtr, int) ; 


// Allocate unmanaged buffer 
IntPtr serial_ptr = Marshal.AllocHGlobal(length * sizeof(int)); 

try 
{ 
    // Call unmanaged function 
    int return_code; 
    int result = primary_read_serial(handle, ref return_code, serial_ptr, length); 

    // Safely marshal unmanaged buffer to byte[] 
    byte[] bytes = new byte[length * sizeof(int)]; 
    Marshal.Copy(serial_ptr, bytes, 0, length); 

    // Converter to int[] 
    int[] ints = new int[length]; 
    for (int i = 0; i < length; i++) 
    { 
     ints[i] = BitConverter.ToInt32(bytes, i * sizeof(int)); 
    } 

} 
finally 
{ 
    Marshal.FreeHGlobal(serial_ptr); 
} 

Đừng quên cố gắng cuối cùng, hoặc bạn sẽ có nguy cơ bị rò rỉ xử lý không được quản lý.

+0

Cụ thể, phân bổ mảng không được quản lý và int [] được quản lý và Marshal.Copy IntPtr của bạn từ mảng không được quản lý đến mảng được quản lý. –

+1

try-catch hoặc try-finally? – MedicineMan

+0

cố gắng cuối cùng, cảm ơn vì đã chỉ ra. Đã sửa. – Coincoin

0

Khi viết P/gọi tuyên bố của chức năng đó, hãy thử sử dụng từ khóa ref cho các tham số con trỏ như thế này:

[DllImport("YouDll.dll", EntryPoint = "primary_read_serial")] 
public static extern int primary_read_serial(int, ref int, ref int, int) ; 

Tôi không chắc chắn nếu bạn cần phải xác định tên các thông số trong C#. Và hãy nhớ rằng, khi gọi phương thức đó, bạn cũng sẽ phải sử dụng ref trong các đối số mà bạn truyền qua tham chiếu.

+0

Nếu nó được coi là một mảng anh ta cần phải chắc chắn để vượt qua như là một IntPtr và Marshal.Copy đến một mảng quản lý tuy nhiên. –

2

Nếu tôi hiểu những gì bạn đang cố gắng làm, điều này sẽ phù hợp với bạn.

unsafe 
{ 
    int length = 1024; // Length of data to read. 

    fixed (byte* data = new byte[length]) // Pins array to stack so a pointer can be retrieved. 
    { 
     int returnCode; 
     int retValue = primary_read_serial(0, &returnCode, data, length); 

     // At this point, `data` should contain all the read data. 
    } 
} 

JaredPar cung cấp cho bạn một cách dễ dàng để làm điều đó tuy nhiên, mà chỉ là để thay đổi khai báo hàm bên ngoài của bạn để C# hiện marshalling cho bạn ở chế độ nền.

Hy vọng điều này mang đến cho bạn ý tưởng về những gì đang xảy ra ở mức thấp hơn một chút.

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