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

时间:2010-12-15 21:42:35

标签: c# c++ interop

我正在使用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

2 个答案:

答案 0 :(得分:4)

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

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

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

答案 1 :(得分:1)

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

相关问题