DllImport и char * - PullRequest
       27

DllImport и char *

6 голосов
/ 02 апреля 2010

У меня есть метод, который я хочу импортировать из 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.

Ответы [ 3 ]

8 голосов
/ 02 апреля 2010

Похоже, что функция GetDriveLetter ожидает значение char*, которое указывает на достаточное количество памяти для размещения буквы диска.

Я думаю, что самый простой способ решить эту проблему - передать необработанный IntPtr и обернуть вызовы к GetDriveLetter в 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);
  }
}
0 голосов
/ 08 марта 2013
[DllImport("mydll.dll")]
public static extern bool GetDriveLetter([MarshalAs(UnmanagedType.LPStr)]  string DriveLetter)
0 голосов
/ 02 апреля 2010

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 () , например.

...