Как вывести строку из нативного кода

Имея встроенную функцию, которая возвращает строку (как char *) по параметру, что было бы лучшим вариантом между предварительным выделением char * через управляемый код и передачей его по параметру и выделением char * из собственного кода, а затем выпуском это из с #?

не могли бы вы объяснить мне, почему я должен использовать один над другим? Пожалуйста, отвечайте, только если есть определенная причина, чтобы предпочесть решение другому. Если вместо этого все решения в порядке, мой вопрос также может считаться ответом.

В качестве бонуса я хотел бы знать, как я должен выделить переменную char * из C# в первом случае (с использованием класса Marshal или с простым new или с StringBuilder, как я часто вижу в других ответах?) И как я должен удалить указатель, если вместо этого я создаю переменную char * из собственного кода во втором случае.

1 ответ

Решение

Обычно не рекомендуется возвращать char* от функции C и ожидаем, что он будет отменен вызывающим. Вызывающая сторона может этого не делать (правильно или вообще) и, таким образом, утечка памяти. Один из распространенных способов избежать этого (как его используют 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затем снова с выделенным массивом символов, пока 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

Надеюсь, это поможет!

Другие вопросы по тегам