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

发布于 2024-10-21 01:55:14 字数 501 浏览 3 评论 0原文

假设我在 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 返回的字符串不会被释放、删除或执行其他操作同样糟糕。希望问题很清楚。提前致谢

suppose I have x.dll in C++ which looks like this

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

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

Now, suppose I want to use this in C#

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

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

Is there any way to tell CLR to take strong ownership of the string returned from f2, but not f1? The thing is that the fact that the string returned from f1 will eventually be freed, deleted, or whatever by GC is equally bad with the fact that the string returned from f2 won't. Hope the question was clear. Thanks in advance

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

鼻尖触碰 2024-10-28 01:55:14

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

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

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

本机:

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

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

If you have any influence at all over the dll implementation, then I strongly suggest you simply don't do it like you showed in your example. Otherwise, please refine the question to mention that constraint.

If you have to return a heap allocated string from the dll, then you should also provide a cleanup function (always good practice when exporting dynamically allocated memory from a dll). You P/Invoke the allocating function with a return of IntPtr and marshal that with one of the Marshal.PtrToString... at http://msdn.microsoft.com/en-us/library/atxe881w.aspx and finish off by calling the cleanup function for the native side of things.

Another way is to use BSTR (example from Marshaling BSTRs in COM/Interop or P/Invoke):

Native:

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

Managed:

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

I just found a similar question on SO: PInvoke for C function that returns char *

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文