Передача String из C # в C ++ DLL с различной кодировкой текста для разных типов возврата - PullRequest
0 голосов
/ 30 августа 2018

Надеюсь, кто-нибудь может объяснить, в чем именно разница:

В моей программе на C # я хочу передать строку в метод C ++. Мой код в C # выглядит так:

    [DllImport("Test.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
    public static extern String DoIt(String filename);

Внутренняя часть моей C ++ DLL выглядит так:

__declspec(dllexport) CString DoIt(char* szFilename)
{
....
}

Если я передаю строку (например: C: \ temp \ my.txt), она становится деформированной => "Ôœ & ° 8é -".

Теперь наступает запутанная часть, которую я не могу понять. Если я изменю тип возврата с CString на char *, то все в порядке.

__declspec( dllexport ) char* DoIt(char* filename)

Почему это так? CharSet в C # уже настроен на Ansi для маршала String в нужный тип. Я не могу понять, где находится связь между типом возврата и моей передаваемой строкой.

Если вам нужна дополнительная информация, просто дайте мне знать.

1 Ответ

0 голосов
/ 30 августа 2018

Обе версии вашего кода неверны. Вы, конечно, не можете передать CString как тип взаимодействия. Вы можете использовать простые типы для взаимодействия, а не классы C ++.

Ошибка при использовании char* более тонкая. В этом сценарии есть две проблемы.

Во-первых, с типом возврата string на стороне C # маршаллер pinvoke предполагает, что возвращаемая строка была выделена с помощью CoTaskMemAlloc, и вызовет CoTaskMemFree, чтобы освободить ее после ее копирования.

Во-вторых, хотя мы этого не видим, ваш код C ++ почти наверняка возвращает указатель на буфер, принадлежащий локальной переменной в функции C ++. Очевидно, что эта локальная переменная выходит из области видимости, когда функция возвращается и указатель становится недействительным.

Некоторые опции:

  1. Пусть вызывающий найдет строковый буфер и позволит вызываемому заполнить его.
  2. Распределите возвращенный char*, используя CoTaskMemAlloc, и, таким образом, соответствует ожиданиям кода C #.
  3. Используйте тип COM BSTR, который понимает маршаллер pinvoke.
...