【问题标题】:Passing string from C++ to C#将字符串从 C++ 传递到 C#
【发布时间】:2010-12-15 21:42:35
【问题描述】:

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

除了将字符串从 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

【问题讨论】:

    标签: c# c++ interop


    【解决方案1】:

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

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

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

    【讨论】:

    • 您能详细说明一下吗?我的 c# 不够专业,不知道如何实现您的答案。
    • @ravenspoint 尝试将委托更改为:public delegate void callback([MarshalAs(UnmanagedType.BStr)] string str);,如果需要,导入 System.Runtime.InteropServices 命名空间。这告诉运行时非托管代码期望这是一个 BSTR(或者可能是 BSTR *,我不是互操作专家)
    • 做到了!非常感谢。
    【解决方案2】:

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

    【讨论】:

    • 是的,我相信 BSTR 也是如此。
    • BSTR 不是普通的 wchar_t*s,它们是不同的二进制格式。这就是 SysAllocString 存在的原因。
    • 是的。它们前面是字符串长度。据我了解,BSTR(c++) == string(c#)
    猜你喜欢
    • 1970-01-01
    • 2012-02-12
    • 1970-01-01
    • 2015-12-23
    • 2014-02-24
    • 1970-01-01
    • 2011-03-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多