2010-04-02 50 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)