将字符串从C ++传递到C#

我正在使用Photvm,反向PInvoke方案,如Thottam R. Sriram所述http://blogs.msdn.com/b/thottams/archive/2007/06/02/pinvoke-reverse-pinvoke-and-stdcall-cdecl。 ASPX

除了将字符串从C ++传递给C之外,一切似乎都运行良好。

(在Sriram中,字符串是用c#构造的,并且通过c ++不受影响,所以避免了这个问题。)

c#代码看起来像这样

class Program { public delegate void callback(string str); public static void callee(string str) { System.Console.WriteLine("Managed: " + str); } static void Main(string[] args) { gpscom_start(new callback(Program.callee)); Console.WriteLine("NMEA COM Monitor is running"); System.Threading.Thread.Sleep(50000); } [DllImport("gpscomdll.dll", CallingConvention = CallingConvention.StdCall)] public static extern void gpscom_start(callback call); } 

C ++代码看起来像这样

 extern "C" dllapi void __stdcall gpscom_start(void (__stdcall *callback) (BSTR str)) { BSTR bstr = SysAllocString(L"starting monitor"); (*callback)(bstr); SysFreeString(bstr); 

运行时,除回调字符串外,一切看起来都很好

 Managed: m 

它看起来像是由ANSI例程打印出来的UNICODE字符串,但是c#字符串肯定是unicode吗?

TIA

在跨P / Invoke边界编组字符串时,最好使用具有相应字符串类型的MarshalAs属性。 我认为在参数上放置一个[MarshalAs(UnmanagedType.BStr)]可以解决这个问题。

 public delegate void callback([MarshalAs(UnmanagedType.BStr)]string str); 

本文有一个类似的例子,有人在托管代码和非托管代码之间传递BSTR,但他在Marshal类上使用了IntPtr和一些方法。 Marshal.PtrToStringBSTR似乎在这里最有用。

C#字符串是UTF-16。 我建议C#可以期待LPWSTR或类似的东西,而不是BSTR。 如果您查看发布的第一个示例,他会将调用类型设置为wchar_t *,而不是BSTR。