如何指定是否取得编组字符串的所有权?

Arm*_*yan 7 c# c++ interop marshalling

假设我在C++中有x.dll,看起来像这样

MYDLLEXPORT
const char* f1()
{
   return "Hello";
}

MYDLLEXPORT
const char* f2()
{
   char* p = new char[20];
   strcpy(p, "Hello");
   return p;   
}
Run Code Online (Sandbox Code Playgroud)

现在,假设我想在C#中使用它

[DllImport("x.dll")]
public static extern string f1();

[DllImport("x.dll")]
public static extern string f2();
Run Code Online (Sandbox Code Playgroud)

有没有办法告诉CLR对从f2返回的字符串采取强有力的所有权,但不是f1?事实是,从f1返回的字符串最终将被GC释放,删除或其他任何事实同样糟糕的事实是从f2返回的字符串不会.希望问题很清楚.提前致谢

Joh*_*ell 5

如果您对 dll 实现有任何影响,那么我强烈建议您不要像示例中所示那样进行操作。否则,请细化问题以提及该限制。

如果您必须从 dll 返回一个堆分配的字符串,那么您还应该提供一个清理函数(从 dll 导出动态分配的内存时总是好的做法)。您可以使用http://msdn.microsoft.com/en-us/library/atxe881w.aspx中的一个返回来 P/Invoke 分配函数IntPtr并对其进行编组,然后通过调用本机端的清理函数来完成东西的。Marshal.PtrToString...

另一种方法是使用BSTR(来自COM/Interop 或 P/Invoke 中的封送 BSTR 的示例):

本国的:

__declspec(dllexport)
void bstrtest(BSTR *x)
{
    *x = SysAllocString(L"Something");
}
Run Code Online (Sandbox Code Playgroud)

管理:

[DllImport("mydll.dll")]
extern static void bstrtest(ref IntPtr dummy);

static void Main(string[] args)
{
    var bstr = IntPtr.Zero;
    bstrtest(ref bstr);

    var text = Marshal.PtrToStringBSTR(bstr);
    Console.WriteLine(text);

    Marshal.FreeBSTR(bstr);
}
Run Code Online (Sandbox Code Playgroud)

我刚刚在 SO: PInvoke for C function that returns char *上发现了类似的问题