【问题标题】:How to marshal an out string from native code [duplicate]如何从本机代码编组输出字符串[重复]
【发布时间】:2017-06-30 01:29:21
【问题描述】:

拥有一个通过参数返回字符串(作为 char *)的本机函数,在通过托管代码预分配 char * 并通过参数传递它并从本机代码内部分配 char * 之间的最佳选择是什么然后从 c# 中释放它?

您能否向我解释一下为什么我应该使用其中一个而不是另一个?请仅在有特定原因偏爱某个解决方案而不是另一个解决方案时才回答。如果任一解决方案都可以,我的问题也可以被视为已回答。

作为奖励,我想知道在第一种情况下我应该如何从 c# 分配 char * 变量(使用 Marshal 类或使用简单的 new 或使用 StringBuilder,就像我在其他答案中经常看到的那样?)以及如何如果我在第二种情况下从本机代码中创建 char * 变量,我应该删除指针。

【问题讨论】:

  • 请删除原版。我昨天居然标记为删除,肯定有人恢复了!原来的也没有答案,只有一条评论
  • @Flexo:这个骗子已经被删除了,这个问题虽然有点“软”,但似乎确实是话题并且有一个不错的答案。请考虑重新打开它吗?

标签: c# mixed-mode


【解决方案1】:

从 C 函数返回 char* 并期望调用者将其释放通常不是一个好习惯。调用者可能不这样做(正确或根本不这样做),因此会泄漏内存。避免这种情况的一种常见方法(如 OpenGL、OpenCL 和我见过的其他库所使用的)是将原型声明为:

int GetString(char* str, int* len);

这样的实现:

int GetString(char* str, int* len)
{
    if (str == NULL)
    {
        len = internal_get_string_length();
        return 0; // No errors
    }
    else
    {
        if (len <= internal_get_string_length())
            return -1; // not enough space in str
        char* internal_str = internal_get_string_ptr();
        strcpy(str, internal_str);
        return 0;
    }
}

然后文档将说明如果str 为NULL,则要返回的字符串的长度在len 中返回。否则,指针str 应包含所需的字符数。为了使用它,用户调用该函数两次,一次为str 使用NULL,len 使用int,然后再次使用分配的char 数组,只要len。 P/Invoking 这类函数的一个可能原型是:

// Declaration
[DllImport("myDll.dll")]
int GetString(StringBuilder sb, ref int len);

// Usage
int length;
GetString(null, length);
var sb = new StringBuilder(length); // Set capacity
GetString(sb, length);
Console.WriteLine(sb.ToString()); // Do stuff with C# string

希望有帮助!

【讨论】:

  • 有点尴尬但至少我现在有了更好的理解
猜你喜欢
  • 2012-11-19
  • 2020-01-27
  • 2023-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-06
  • 1970-01-01
  • 1970-01-01
  • 2011-12-06
相关资源
最近更新 更多