2010-04-02 21 views
5

Tôi có một phương pháp tôi muốn nhập khẩu từ một DLL và nó có một chữ ký của:DllImport và char *

BOOL GetDriveLetter(OUT char* DriveLetter) 

Tôi đã thử

[DllImport("mydll.dll")] 
    public static extern bool GetDriveLetter(byte[] DriveLetter); 

[DllImport("mydll.dll")] 
    public static extern bool GetDriveLetter(StringBuilder DriveLetter); 

nhưng không trả lại bất kỳ thứ gì trong biến DriveLetter.

Trả lời

6

Có vẻ như chức năng GetDriveLetter đang mong đợi một char* trỏ đến đủ bộ nhớ để chứa ký tự ổ đĩa.

Tôi nghĩ cách dễ nhất để tiếp cận vấn đề này là chuyển số IntPtr thô và chuyển các cuộc gọi đến GetDriveLetter trong API quản lý và chuyển đổi tài nguyên thành string.

[return:MarshalAsAttribute(UnmanagedType.Bool)] 
private static extern bool GetDriveLetter(IntPtr ptr); 

public static bool GetDriveLetter(out string drive) { 
    drive = null; 
    var ptr = Marshal.AllocHGlobal(10); 
    try { 
    var ret = GetDriveLetter(ptr); 
    if (ret) { 
     drive = Marshal.PtrToStringAnsi(ptr); 
    } 
    return ret; 
    } finally { 
    Marshal.FreeHGlobal(ptr); 
    } 
} 
+0

UnmanagedType.I1 có nghĩa là gì? – Malfist

+0

@Malfist, Giá trị I1 yêu cầu CLR so khớp giá trị dưới dạng số nguyên 1 byte. Nó thực sự không chính xác trong mẫu này vì I4 là giá trị đúng (cập nhật một chút trước). Về lý do tại sao hãy kiểm tra mục nhập blog này tôi đã viết trên các giá trị bool marshalling: http://blogs.msdn.com/jaredpar/archive/2008/10/14/pinvoke-and-bool-or-should-i-say-bool .aspx – JaredPar

+0

Khi tôi tạo I4, tôi nhận được MarshalDirectiveException – Malfist

0

StringBuilder có lẽ là cách để đi, nhưng bạn phải đặt công suất của trình tạo chuỗi trước khi gọi hàm. Vì C# không biết có bao nhiêu bộ nhớ mà GetDriveLeter sẽ sử dụng, bạn phải chắc chắn rằng StringBuilder có đủ không gian. Sau đó, marshaller sẽ vượt qua một mức độ được gán cho chiều dài đó cho hàm và marhsall nó quay trở lại StringBuilder.

[return:MarshalAsAttribute(UnmanagedType.I4)] 
private static extern bool GetDriveLetter(StringBuilder DriveLetter); 

public static bool GetDriveLetter(out string driverLetter) { 
    StringBuilder buffer = new StringBuilder(10); 
    bool ret = GetDriveLetter(buffer); 
    driveLetter = buffer.ToString(); 
    return ret; 
} 

Xem p/invoke sample for GetWindowText(), ví dụ.

+0

Không trả về đúng chuỗi, không giống như câu trả lời được chấp nhận. – Malfist

+0

Nếu bạn thêm CharSet = CharSet.Ansi vào thuộc tính DllImport thì sao? Đó là nếu bạn quan tâm vì bạn có một giải pháp làm việc. – shf301

+0

thêm CharSet.Ansi vào DllImport không tạo ra sự khác biệt nào. – Malfist

0
[DllImport("mydll.dll")] 
public static extern bool GetDriveLetter([MarshalAs(UnmanagedType.LPStr)] string DriveLetter)