如何从本机代码封送 out 字符串



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

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

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

从 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应包含所需数量的字符。为了使用它,用户调用该函数两次,一次使用 NULL 表示 str,一次使用 int 表示len,然后再次使用分配的 char 数组,只要 len 即可。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

希望对您有所帮助!

最新更新