Я бы сделал это с BSTR
, так как это означает, что вам не нужно вызывать в native два раза на строку, один раз, чтобы получить длину, а затем один раз, чтобы получить содержимое.
С помощьюBSTR
маршаллер позаботится о том, чтобы освободить BSTR
с помощью правильного менеджера памяти, чтобы вы могли безопасно передать его из своего кода C ++.
C ++
#include <comutil.h>
BSTR GetSomeText()
{
return ::SysAllocString(L"Greetings from the native world!");
}
C #
[DllImport(@"test.dll", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.BStr)]
private static extern string GetSomeText();
Есть один незначительный недостаток BSTR
, а именно, что он несет полезную нагрузку UTF-16, но ваши исходные данные вполне могут быть char*
.
Чтобы преодолеть это, вы можете свернуть преобразование с char*
в BSTR
следующим образом:
BSTR ANSItoBSTR(const char* input)
{
BSTR result = NULL;
int lenA = lstrlenA(input);
int lenW = ::MultiByteToWideChar(CP_ACP, 0, input, lenA, NULL, 0);
if (lenW > 0)
{
result = ::SysAllocStringLen(0, lenW);
::MultiByteToWideChar(CP_ACP, 0, input, lenA, result, lenW);
}
return result;
}
Это самый сложный способ, и теперь его легко добавитьдругие оболочки для преобразования в BSTR
из LPWSTR
, std::string
, std::wstring
и т. д.