2010-04-02 49 views
5

我有我想從一個DLL導入的方法和它的簽名:我已經試過的DllImport與char *

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

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

BOOL GetDriveLetter(OUT char* DriveLetter) 

但在DriveLetter變量中都沒有返回任何內容。

回答

6

它看起來功能GetDriveLetter期待char*它指向足夠的內存來包含驅動器號。

我認爲解決這個問題的最簡單的方法是通過原始IntPtr並負責資源管理和轉換到string的API在換到GetDriveLetter呼叫。

[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是什麼意思? – Malfist 2010-04-02 19:58:04

+0

@Malfist,值I1告訴CLR將該值編組爲1字節整數。在這個例子中它實際上是不正確的,因爲I4是正確的值(稍後更新)。至於爲什麼看看我編寫的關於編組布爾值的博客條目:http://blogs.msdn.com/jaredpar/archive/2008/10/14/pinvoke-and-bool-or-should-i-say-bool .aspx – JaredPar 2010-04-02 20:00:05

+0

當我把它做成I4時,我得到MarshalDirectiveException – Malfist 2010-04-02 20:34:48

0

StringBuilder可能是要走的路,但您必須在調用函數之前設置字符串生成器的容量。由於C#不知道GetDriveLeter將使用多少內存,您必須確保StringBuilder有足夠的空間。然後,編組將把分配給該長度的char*傳遞給函數,並將其返回給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; 
} 

查看p/invoke sample for GetWindowText(),舉個例子。

+0

不像接受的答案那樣返回正確的字符串。 – Malfist 2010-04-02 21:06:52

+0

如果將CharSet = CharSet.Ansi添加到DllImport屬性會怎麼樣?這就是如果你關心,因爲你有一個工作解決方案。 – shf301 2010-04-02 22:13:46

+0

將CharSet.Ansi添加到DllImport沒有區別。 – Malfist 2010-04-05 17:05:37

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