Проблема с выводом строки в c# после экспорта из c dll

Я подключил dll к моему коду С#, чтобы вернуть из него строку:

extern "C" __declspec(dllexport) Dll_NIRS_API void realize(char*) 
void realize(char* buf) 
{
...
    wstring full_text;
    // operations with full_text 

    char* fill = (char*)(full_text.c_str());
    strcpy(buf, fill);

}

Подключение к С#:

[DllImport("dll_name.dll", CharSet = CharSet.Unicode)]
        public static extern void realize(StringBuilder text);

Затем я использую эту функцию и помещаю полученную строку в текстовое поле:

            StringBuilder text = new StringBuilder(100);
            realize(text);
            textBox4.Text = text.ToString();

Но вместо текста: РАЗВОРОТ(1, 1.1, 1.2, 1.3, 1.4) РАЗВОРОТ(1, 2.1, 2.2, 2.3, 2.4) текстовое поле выводит это: РАЗВОРОТ (듹翼

Переменная "full_text" заполнена правильно, а вот насчёт переменной "fill" не уверен, возможно проблема в strcpy или в экспорте dll. Я использую StringBuilder по совету из этого вопроса: Передача строк из C# в C++ DLL и обратно - минимальный пример

РЕДАКТИРОВАТЬ Частично решил проблему, теперь в textBox отображается весь текст (а не только его часть, как было раньше). Я только что преобразовал full_text из wstring в string для использования в strcpy. Я также изменил CharSet.Unicode на CharSet.Ansi. Однако теперь текст выглядит так: Р РђР—Р’РћР РћРў(1, 1.1, 1.2, 1.3, 1.4)Р РђР—Р’РћР’РћРў(1, 2.1, 2.2, 2.3, 2.4)

Разве realize(text); не вызывает проблем, поскольку void realize(char* buf) ожидает char *, а не StringBuilder?

chux - Reinstate Monica 21.11.2022 10:26

Я нашел такое решение с stringBuilder, чтобы использовать строки из c dll в C#

Daria 21.11.2022 10:35

@Daria Если ваш комментарий означает, что вы пытались следовать примеру, который вы где-то нашли, пожалуйста, отредактируйте свой вопрос и добавьте ссылку на этот пример. Ваш прототип функции C# realize не соответствует прототипу и реализации C++, поэтому это неопределенное поведение. Даже если память объекта StringBuilder совместима со строкой C, могут быть разные кодировки.

Bodo 21.11.2022 11:25

Я отредактировал вопрос и добавил ссылку

Daria 21.11.2022 12:14

Вам нужно будет указать CharSet = CharSet.Ansi или изменить параметр buf на wchar_t*. Осторожно, ваш код опасен, так как strcpy с радостью перезапишет память, которую вы не выделили. Обычно вы должны передать функции C другой параметр, указывающий максимальный размер строки.

Klaus Gütter 21.11.2022 13:00

@ Клаус Гюттер Я изменил CharSet на CharSet.Ansi и преобразовал full_text из wstring в string. Стало лучше, но я тоже вижу непривычно символы (я отредактировал свой вопрос)

Daria 21.11.2022 13:52

Проблема с кодировкой. Возможно, ваш string в UTF8?

Klaus Gütter 21.11.2022 14:05

@ Клаус Гюттер да, это UTF8. Должен ли я перейти на UTF16? Как я могу это сделать?

Daria 21.11.2022 14:10

Если это возможно: да. Затем вернитесь к CharSet.Unicode и wstring, но измените параметр на wchar_t* и strcpy на wcscpy.

Klaus Gütter 21.11.2022 14:17
Как настроить Tailwind CSS с React.js и Next.js?
Как настроить Tailwind CSS с React.js и Next.js?
Tailwind CSS - единственный фреймворк, который, как я убедился, масштабируется в больших командах. Он легко настраивается, адаптируется к любому...
LeetCode запись решения 2536. Увеличение подматриц на единицу
LeetCode запись решения 2536. Увеличение подматриц на единицу
Увеличение подматриц на единицу - LeetCode
Переключение светлых/темных тем
Переключение светлых/темных тем
В Microsoft Training - Guided Project - Build a simple website with web pages, CSS files and JavaScript files, мы объясняем, как CSS можно...
Отношения "многие ко многим" в Laravel с методами присоединения и отсоединения
Отношения "многие ко многим" в Laravel с методами присоединения и отсоединения
Отношения "многие ко многим" в Laravel могут быть немного сложными, но с помощью Eloquent ORM и его моделей мы можем сделать это с легкостью. В этой...
В PHP
В PHP
В большой кодовой базе с множеством различных компонентов классы, функции и константы могут иметь одинаковые имена. Это может привести к путанице и...
Карта дорог Беладжар PHP Laravel
Карта дорог Беладжар PHP Laravel
Laravel - это PHP-фреймворк, разработанный для облегчения разработки веб-приложений. Laravel предоставляет различные функции, упрощающие разработку...
0
9
50
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Существует два (простых) варианта сортировки строк с использованием P/Invoke:

  • Либо объявите [CharSet = CharSet.Ansi] в C#, либо char* в C. Для этого требуется, чтобы библиотека C использовала набор символов "ANSI", что здесь, похоже, не так.
  • Или объявить [CharSet = CharSet.Unicode] в C# и иметь wchar_t* в C

Для второго варианта последними утверждениями должны быть:

wchar_t* fill = full_text.c_str();
wcscpy(buf, fill);

Большое предостережение: strcpy/wcscpy опасны, так как могут перезаписать память, которую вы не выделили. Настоятельно рекомендую заменить на:

wcscpy_s(buf, size, fill);

Size будет размером буфера (максимальное количество символов, включая завершающий NUL) и должен быть передан в метод как дополнительный параметр.

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