2016-05-30 9 views
0

Есть C++ ActiveX OCX со следующей декларацией ODL:Как преобразовать C++ PBSTR в C# строка

DISP_FUNCTION(CHellerCommCtrl, "GetRecipePath", GetRecipePath, VT_I4, VTS_PBSTR) 

нужно позвонить GetRecipePath из C программы # и преобразовать результирующую C++ BSTR в C# строку. знает, от других сообщений, следующим решения:

string s1 = Marshal.PtrToStringAnsi((IntPtr)outPtr); 

Проблемы, прототип GetRecipePath в C# с помощью Interop имеет аргумент «реф строку» и не позволит мне типаж результирующей «строки» в «IntPtr», а затем передать это методу маршала. Как преобразовать «строку», полученную из GetRecipePath [которая действительно является BSTR], в строку C#?

+0

C++ является байт [], который заканчивается на '\ 0'. Используйте Encoding.UTF8.GetString (byte []) для преобразования в строку. – jdweng

+0

Я дам ваше предложение попробовать, но должен отметить, что BSTR является строкой Unicode, а не строкой байта [ASCII]. Я считаю, что это то, что делает метод Маршалла, конвертирует Unicode в ASCII. –

+0

Не клади слова в рот. Я никогда не использовал ASCII. Если у вас есть два байтовых символа, чем использование кодировки Unicode вместо UTF8. Ascii удаляет непечатаемые символы. – jdweng

ответ

-1

A BSTR - это не просто указатель на строку в Юникоде, а префикс длины, выделенной и освобожденной с помощью определенного api и подразумевает изменение прав собственности при передаче другому методу.

Если ваш outPtr является, BSTR, то вы можете сделать следующее:

string s1 = Marshal.PtrToStringBSTR(outPtr) 

Я не уверен, если Marshal.PtrToStringBSTR() освобождает BSTR для вас (документация не явно об этом), но если это вы не можете позвонить по телефону Marshal.FreeBSTR(outPtr).

Кроме того, вы можете использовать строку в управляемом COM-интерфейсе и украсить ее [MarshalAs(UnmanagedType.BStr)]. К сожалению, я не очень хорошо знаком с DISP_FUNCTION или IDispatch, но я думаю, сигнатуру метода в C#, чтобы быть что-то вроде этого:

[PreserveSig] 
int GetRecipePath([MarshalAs(UnmanagedType.BSTR)] out string path); 

Или еще лучше:

строка
[return: MarshalAs(UnmanagedType.BSTR)] 
string GetRecipePath(); 
+0

Судя по имени метода 'GetRecipePath', я предполагаю, что VTS_PBSTR обозначает аргумент' [out, retval] 'i, т. Е. Указатель BSTR –