问题
I have the following signature of a C++ method. The last argument should return the device name as a 2 byte unicode string.
int GetDeviceIdentifier(DWORD deviceIndex, WCHAR** ppDeviceName);
I wrapped into C# with the following signature. It works but the string that I get is strange. Am I doing something wrong?
[DllImportAttribute("StclDevices.dll", EntryPoint = "GetDeviceIdentifier", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
public static extern int GetDeviceIdentifier(uint deviceIndex, StringBuilder ppDeviceName);
回答1:
Passing a StringBuilder
parameter would match a C++ parameter of type WCHAR*
. In that case the memory would be allocated by the C# code by setting the capacity of the string builder object.
For your function it would appear that the memory is allocated by the C++ code. Hence the double pointer. So you would need this:
[DllImportAttribute("StclDevices.dll",
CallingConvention=CallingConvention.Cdecl)]
public static extern int GetDeviceIdentifier(
uint deviceIndex,
out IntPtr ppDeviceName
);
You call it like this:
IntPtr ppDeviceName;
int retval = GetDeviceIdentifier(deviceIndex, out ppDeviceName);
string DeviceName = Marshal.PtrToStringUni(ppDeviceName);
回答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);
If you want to stick on StringBuilder, use this instead:
[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);
来源:https://stackoverflow.com/questions/14342140/how-to-get-unicode-string-from-c-to-c-sharp-using-pinvoke