У меня есть библиотека .net, которая зарегистрирована как COM-объект, при импорте файла .tlb в проект C ++ я получаю такое объявление метода
virtual HRESULT __stdcall GetBid ( /*[in]*/ BSTR symbol, /*[out,retval]*/ double * pRetVal ) = 0;
для эквивалента .NET
double GetBid(string symbol);
сейчас я пытаюсь назвать это так
double bid;
ptr->GetBid(_T("AAPL"), &bid);
что не работает должным образом, потому что на стороне .NET строковый параметр на самом деле является пустой строкой.
Если я перейду на такой звонок
double bid;
ptr->GetBid(_bstr_t("AAPL"), &bid);
все работает как положено.
Почему оба вызова скомпилированы нормально, но результат отличается? Разве первый вызов не должен быть преобразован в правильный маршалинг строки?
Спасибо за любую под капотом информацию о магии БСТР 🙂
BSTR имеет 32-битную длину предшествующего строка. Таким образом, BSTR может содержать встроенные нули.
_T («AAPL») создает wchar_t * с завершающим нулем, но без префикса длины.
Однако оба они wchar_t *, поэтому вызов компилируется и преобразование не требуется. Тебе несколько повезло, потому что могло случиться что-то худшее, чем просто не натянуть веревку на другой стороне. Маршалер может взглянуть на счетчик _T («AAPL») обратно 32-битным, и, если повезет, получит значение длинной длины reeeeaalally, что было бы плохо. 🙂
Вы получите автоматическое преобразование, если параметр будет определен как _bstr_t, так как это вызовет конструктор _bstr_t (wchar_t *).
Так как BSTR является указателем на строку широких символов, но это не значит, что вы можете просто назначить простую const wchar_t * string. Для работы с BSTR необходимо использовать несколько системных функций, строка SysAllocString () для создания БСТР. Класс _bstr_t инкапсулирует все это