【问题标题】:How to specify whether to take ownership of the marshalled string or not?如何指定是否拥有编组字符串的所有权?
【发布时间】:2011-07-11 09:58:55
【问题描述】:

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

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

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

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

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

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

有没有办法告诉 CLR 对从 f2 返回的字符串而不是 f1 获得强所有权?事实是,从 f1 返回的字符串最终将被 GC 释放、删除或其他任何事情,而从 f2 返回的字符串不会。希望问题很清楚。提前致谢

【问题讨论】:

    标签: c# c++ interop marshalling


    【解决方案1】:

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

    如果您必须从 dll 返回一个堆分配的字符串,那么您还应该提供一个清理功能(从 dll 导出动态分配的内存时总是很好的做法)。你 P/Invoke 分配函数,返回 IntPtr 并用 Marshal.PtrToString... 之一在 http://msdn.microsoft.com/en-us/library/atxe881w.aspx 封送该函数,并通过调用本机方面的清理函数来结束。

    另一种方法是使用BSTR(示例来自Marshaling BSTRs in COM/Interop or P/Invoke):

    本地人:

    __declspec(dllexport)
    void bstrtest(BSTR *x)
    {
        *x = SysAllocString(L"Something");
    }
    

    托管:

    [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);
    }
    

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

    【讨论】:

    • 谢谢。抱歉,我无法为您投票(已达到每日上限),您提供的链接正是我所需要的!
    • @Armen: 你明天随时可以回来... ;)
    猜你喜欢
    • 1970-01-01
    • 2019-06-11
    • 1970-01-01
    • 1970-01-01
    • 2010-10-12
    • 2013-04-08
    • 1970-01-01
    相关资源
    最近更新 更多