如何使用的PInvoke从C ++得到unicode字符串到C#(How to get unicod

2019-10-17 14:47发布

我有一个C ++方法的以下签名。 最后一个参数应该返回的设备名称为2个字节的unicode字符串。

int GetDeviceIdentifier(DWORD deviceIndex, WCHAR** ppDeviceName);

我裹成C#与下面的签名。 它的工作原理,但我得到的字符串是奇怪。 难道我做错了什么?

[DllImportAttribute("StclDevices.dll", EntryPoint = "GetDeviceIdentifier", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
public static extern int GetDeviceIdentifier(uint deviceIndex, StringBuilder ppDeviceName);

Answer 1:

传递StringBuilder参数将匹配类型的C ++参数WCHAR* 。 在这种情况下,存储器将由C#代码通过设置字符串生成对象的容量进行分配。

为了您的功能它会出现内存是由C ++代码分配。 因此,双指针。 所以,你需要这样的:

[DllImportAttribute("StclDevices.dll", 
    CallingConvention=CallingConvention.Cdecl)]
public static extern int GetDeviceIdentifier(
    uint deviceIndex, 
    out IntPtr ppDeviceName
);

你这样称呼它:

IntPtr ppDeviceName;
int retval = GetDeviceIdentifier(deviceIndex, out ppDeviceName);
string DeviceName = Marshal.PtrToStringUni(ppDeviceName);


Answer 2:

[DllImportAttribute("StclDevices.dll", CharSet = CharSet.Unicode, ExactSpelling = true)]
internal static extern Int32 GetDeviceIdentifier([In] UInt32 deviceIndex, [MarshalAs(UnmanagedType.LPTStr), Out] out String ppDeviceName);

String ppDeviceName;
NativeMethods.GetDeviceIdentifier(i, out ppDeviceName);

如果你想坚持的StringBuilder的,用这个来代替:

[DllImportAttribute("StclDevices.dll", CharSet = CharSet.Unicode, ExactSpelling = true)]
internal static extern Int32 GetDeviceIdentifier([In] UInt32 deviceIndex, [In, Out] StringBuilder ppDeviceName);

StringBuilder ppDeviceName = new StringBuilder(255);
NativeMethods.GetDeviceIdentifier(i, ppDeviceName);


文章来源: How to get unicode string from C++ to C# using PInvoke