如何从本机代码编组输出字符串

时间:2017-02-11 20:14:43

标签: c# mixed-mode

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

你可以向我解释为什么我要用一个而不是另一个?请仅在有特定原因选择解决方案时才能回答。如果相反,任何解决方案都可以,我的问题也可以被认为是回答。

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

1 个答案:

答案 0 :(得分:2)

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

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,然后再为len分配一个char数组。 P /调用此类函数的可能原型是:

// 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

希望有所帮助!