2009-06-28 19 views
8

tôi cần sự giúp đỡ của bạn với các tình huống sau:Làm thế nào tôi có thể truyền dữ liệu MemoryStream để không được quản lý C++ DLL sử dụng P/Invoke

Tôi đọc một số dữ liệu từ phần cứng vào một MemoryStream (C#) và tôi cần phải vượt qua dữ liệu này trong bộ nhớ để một dll thực hiện trong không được quản lý C + + (sử dụng con trỏ ??). Dữ liệu đọc (vào luồng) rất lớn (megabyte). Tôi hiểu rằng tôi có thể P/Gọi dll này nhưng những gì tôi không chắc chắn là làm thế nào để vượt qua con trỏ/tài liệu tham khảo của các dòng dữ liệu vào C + + API?

Tôi phải thừa nhận mình bị nhầm lẫn vì tôi mới sử dụng C# - tôi có cần sử dụng không an toàn/cố định vì dữ liệu lớn hay không liên quan như đối tượng MemoryStream do GC quản lý? Một số mã ví dụ/mô tả chi tiết sẽ rất hữu ích. Cảm ơn

Chữ ký của API không được quản lý:

BOOL doSomething (void * rawData, int dataLength)

+0

Loại dữ liệu nào yêu cầu C++? – scottm

+0

Nó yêu cầu dữ liệu thô - byte/void *. Tôi có thể thay đổi API dll theo yêu cầu. –

Trả lời

12

Nếu nó chỉ mong byte bạn có thể đọc MemoryStream vào một mảng byte và sau đó vượt qua một con trỏ đến đó để phương pháp.

Bạn phải khai báo các phương pháp bên ngoài:

[DllImport("mylibrary.dll", CharSet = CharSet.Auto)] 
public static extern bool doSomething(IntPtr rawData, int dataLength); 

Sau đó, đọc các byte từ MemoryStream vào một mảng byte. Phân bổ một GCHandle đó:

Khi phân bổ, bạn có thể sử dụng một GCHandle để ngăn chặn các đối tượng quản lý từ được thu thập bởi các rác nhà sưu tập khi một khách hàng không được quản lý giữ tài liệu tham khảo mà thôi. Nếu không có một tay cầm, đối tượng có thể được thu thập bởi người thu gom rác trước khi hoàn thành công việc của mình thay mặt cho khách hàng không được quản lý.

Và cuối cùng, sử dụng phương thức AddrOfPinnedObject để nhận IntPtr để chuyển tới tệp C++.

private void CallTheMethod(MemoryStream memStream) 
{ 
    byte[] rawData = new byte[memStream.Length]; 
    memStream.Read(rawData, 0, memStream.Length); 

    GCHandle rawDataHandle = GCHandle.Alloc(rawData, GCHandleType.Pinned); 
    IntPtr address = handle.AddrOfPinnedObject(); 

    doSomething(address, rawData.Length); 
    rawDataHandle.Free(); 
} 
+0

Cảm ơn. Có phương pháp này về cơ bản là để nén vì vậy nó sẽ yêu cầu/hoạt động trên dữ liệu thô được truyền cho nó. Ngoài ra dữ liệu được gắn thẻ không an toàn tò mò được đặt trên heap hoặc ngăn xếp trong C#? –

+0

Giống như mã không được đánh dấu là không an toàn. – scottm

+0

Chỉ cần làm rõ, mã này không được coi là không an toàn. – scottm

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