【问题标题】:DllImport and char*DllImport 和 char*
【发布时间】:2011-02-03 20:03:51
【问题描述】:

我有一个要从 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 变量中都没有返回任何内容。

【问题讨论】:

    标签: c# .net pinvoke marshalling dllimport


    【解决方案1】:

    看来函数GetDriveLetter 需要一个char*,它指向足够的内存来包含驱动器号。

    我认为解决这个问题的最简单方法是传递一个原始的IntPtr 并将对GetDriveLetter 的调用封装在一个负责资源管理和转换为string 的API 中。

    [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 是正确的值(刚刚更新)。至于为什么要查看我写的关于编组布尔值的这篇博文:blogs.msdn.com/jaredpar/archive/2008/10/14/…
    • 当我进入 I4 时,我得到 MarshalDirectiveException
    • @Malfist,对不起,应该是UnmanagedType.Bool。曾经是那些日子之一。
    【解决方案2】:

    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()

    【讨论】:

    • 不返回正确的字符串,不像接受的答案。
    • 如果将 CharSet=CharSet.Ansi 添加到 DllImport 属性会怎样?如果你在乎,因为你有一个可行的解决方案。
    • 将 CharSet.Ansi 添加到 DllImport 没有任何区别。
    【解决方案3】:
    [DllImport("mydll.dll")]
    public static extern bool GetDriveLetter([MarshalAs(UnmanagedType.LPStr)]  string DriveLetter)
    

    【讨论】:

      【解决方案4】:

      我有一个相关的情况,该函数有一个 char * 参数,而我错过了 CharSet 赋值:

      [DllImport("library.dll", CharSet = CharSet.Ansi)]
      public static extern IntPtr MyFunc(string myString);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-01-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多