Я подключил 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)
Я нашел такое решение с stringBuilder, чтобы использовать строки из c dll в C#
@Daria Если ваш комментарий означает, что вы пытались следовать примеру, который вы где-то нашли, пожалуйста, отредактируйте свой вопрос и добавьте ссылку на этот пример. Ваш прототип функции C# realize не соответствует прототипу и реализации C++, поэтому это неопределенное поведение. Даже если память объекта StringBuilder совместима со строкой C, могут быть разные кодировки.
Я отредактировал вопрос и добавил ссылку
Вам нужно будет указать CharSet = CharSet.Ansi или изменить параметр buf на wchar_t*. Осторожно, ваш код опасен, так как strcpy с радостью перезапишет память, которую вы не выделили. Обычно вы должны передать функции C другой параметр, указывающий максимальный размер строки.
@ Клаус Гюттер Я изменил CharSet на CharSet.Ansi и преобразовал full_text из wstring в string. Стало лучше, но я тоже вижу непривычно символы (я отредактировал свой вопрос)
Проблема с кодировкой. Возможно, ваш string в UTF8?
@ Клаус Гюттер да, это UTF8. Должен ли я перейти на UTF16? Как я могу это сделать?
Если это возможно: да. Затем вернитесь к CharSet.Unicode и wstring, но измените параметр на wchar_t* и strcpy на wcscpy.
Существует два (простых) варианта сортировки строк с использованием 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) и должен быть передан в метод как дополнительный параметр.
Разве realize(text); не вызывает проблем, поскольку void realize(char* buf) ожидает char *, а не StringBuilder?