C# 字符串编组和内存管理

C# 字符串编组和内存管理,c#,c++,pinvoke,marshalling,C#,C++,Pinvoke,Marshalling,假设我在库中导出了以下C++函数: void foo(const wchar_t* text); 以及使用该函数的C#代码: [DllImport("bla.dll")] static extern void foo([MarshalAs(UnmanagedType.LPWStr)] string text); void Bar() { string s = "hello"; foo(s); } 当我调用foo时,.net封送处理程序

假设我在库中导出了以下C++函数:

void foo(const wchar_t* text);
以及使用该函数的C#代码:

[DllImport("bla.dll")]
static extern void foo([MarshalAs(UnmanagedType.LPWStr)] string text);

void Bar()
{
    string s = "hello";
    foo(s);
}
  • 当我调用
    foo
    时,.net封送处理程序是否复制字符串,或者指针是否指向
    s
    的缓冲区
  • 如果复制了该值,则何时清理
  • 我必须自己清理吗(大概在
    foo
    )里面
  • 如果是这样,我如何清理内存
  • 如果将
    文本
    编组为:

  • UnmanagedType.LPWStr
  • UnmanagedType.BStr
  • 当我调用foo时,.net封送处理程序是复制字符串还是指针指向s的缓冲区
  • 通过值传递LPWSTR的特定情况意味着托管字符串被固定并直接由本机代码使用。在所有其他情况下,将复制字符串

  • 如果复制了该值,则何时清理
  • 封送拆收器在函数调用返回后执行任何释放

    如果将文本编组为:

  • UnmanagedType.LPWStr
  • UnmanagedType.BStr
  • 最终的行为是相同的,因为传递给本机函数的指针在函数调用返回后无效。对于LPWStr,它将指向托管字符串使用的相同内存(可能在本机函数返回后移动),对于BStr,它将指向封送器分配的临时缓冲区(将在本机函数返回后释放)

    如果需要本机函数获得指针的所有权,则需要传入一个
    IntPtr
    ,该函数指向您以适当方式分配给自己的某个内存(可能通过调用某些本机代码,可能通过使用
    AllocHGlobal
    等)。指针需要由您或本机代码使用相同的机制手动释放

  • 当我调用foo时,.net封送处理程序是复制字符串还是指针指向s的缓冲区
  • 通过值传递LPWSTR的特定情况意味着托管字符串被固定并直接由本机代码使用。在所有其他情况下,将复制字符串

  • 如果复制了该值,则何时清理
  • 封送拆收器在函数调用返回后执行任何释放

    如果将文本编组为:

  • UnmanagedType.LPWStr
  • UnmanagedType.BStr
  • 最终的行为是相同的,因为传递给本机函数的指针在函数调用返回后无效。对于LPWStr,它将指向托管字符串使用的相同内存(可能在本机函数返回后移动),对于BStr,它将指向封送器分配的临时缓冲区(将在本机函数返回后释放)


    如果需要本机函数获得指针的所有权,则需要传入一个
    IntPtr
    ,该函数指向您以适当方式分配给自己的某个内存(可能通过调用某些本机代码,可能通过使用
    AllocHGlobal
    等)。指针需要由您或本机代码使用相同的机制手动释放。

    无副本,.net字符串与const wchar\u t*兼容。BSTR需要复制,封送处理程序会处理它并在调用后销毁副本。没有副本,.net字符串与const wchar\u t*兼容。BSTR需要复制,封送员会处理它并在调用后销毁副本。