DllImport和char*

8

我想从一个DLL中导入一个方法,它的签名是:

BOOL GetDriveLetter(OUT char* DriveLetter)

我已经尝试过

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

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

但是DriveLetter变量没有返回任何内容。

4个回答

8

看起来函数GetDriveLetter需要一个指向足够内存以容纳驱动器号的char*

我认为解决这个问题最简单的方法是传递一个原始的IntPtr,并将对GetDriveLetter的调用包装在一个API中,该API负责资源管理和转换为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);
  }
}

@Malfist,I1的值告诉CLR将该值作为1字节整数进行编组。在此示例中,实际上是不正确的,因为I4是正确的值(稍早更新)。至于为什么,请查看我在布尔值编组方面撰写的博客文章:http://blogs.msdn.com/jaredpar/archive/2008/10/14/pinvoke-and-bool-or-should-i-say-bool.aspx - JaredPar
当我将其设置为I4时,会出现MarshalDirectiveException异常。 - Malfist
@Malfist,抱歉,应该是 UnmanagedType.Bool。今天就是这样的一天。 - JaredPar

1

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 GetWindowText()示例,以获取示例。

不像被接受的答案那样返回正确的字符串。 - Malfist
如果您将CharSet = CharSet.Ansi添加到DllImport属性中会发生什么?这只是一个假设,因为您已经有了一个可行的解决方案。 - shf301
将 CharSet.Ansi 添加到 DllImport 中没有任何区别。 - Malfist

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

0
我曾经遇到过一个相关的情况,函数有一个char *参数,但我忘记了分配CharSet
[DllImport("library.dll", CharSet = CharSet.Ansi)]
public static extern IntPtr MyFunc(string myString);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接