Как лучше конвертировать CString в BSTR, чтобы передать его в качестве параметра "в" в метод COM?
Мне нужно конвертировать CString
экземпляр в правильно распределенном BSTR
и передать это BSTR
в метод COM. Чтобы иметь код, который компилируется и работает одинаково для ANSI и Unicode, я использую CString::AllocSysString()
конвертировать в любой формат CString
на Unicode BSTR.
Поскольку никто не владеет возвращенным BSTR, я должен позаботиться об этом и освободить его после того, как вызов будет выполнен наиболее безопасным для исключения способом и с как можно меньшим количеством кода.
В настоящее время я использую ATL::CComBSTR
для управления жизненным циклом:
ATL::CComBSTR converted;
converted.Attach( sourceString.AllocSysString() ); //simply attaches to BSTR, doesn't reallocate it
interface->CallMethod( converted );
что мне не нравится здесь, это то, что мне нужно два отдельных заявления, чтобы просто построить ATL::CComBSTR
привязан к результату преобразования.
Есть ли лучший способ выполнить ту же задачу?
3 ответа
CComBSTR
перегружены конструкторы для обоих char*
а также wchar_t*
, которые делают звонок SysAllocString()
от вашего имени. Так что явное распределение в вашем фрагменте кода на самом деле не нужно. Следующее будет работать так же хорошо:
ATL::CComBSTR converted = sourceString;
interface->CallMethod(converted);
Кроме того, если у вас нет необходимости использовать преобразованный BSTR
в другом месте вашего кода вы можете выполнить конструирование объекта на месте при вызове метода, например так:
interface->CallMethod(ATL::CComBSTR(sourceString));
То же самое относится к _bstr_t
класс, который можно использовать вместо CComBSTR
если вы не хотите зависимость от ATL.
Одним из запутанных аспектов программирования Windows является управление преобразованием строк стиля Visual Basic в / из строк стиля языка Си. Дело не в том, что это так сложно, просто трудно вспомнить детали. Обычно это делается не часто, и документация MSDN настолько обширна, что трудно найти ответы на ваши вопросы. Но хуже всего то, что вы можете выполнить какой-то тип-трансакцию, которая прекрасно компилируется, но не работает так, как вы ожидаете. Это приводит к тому, что код не работает, и ошибки трудно отследить. После некоторого опыта вы научитесь делать так, чтобы ваши преобразования строк выполняли то, что вы ожидаете.
Строки C - это массивы символов, оканчивающиеся символом NULL. Строки Visual Basic отличаются тем, что длина строки предшествует символам в строке. Итак, строка VB знает свою длину. Кроме того, все строки VB являются Unicode (16 бит на символ). Типы строк
BSTR/C Строковые преобразования требуются, если:
You are doing COM programming in C/C++
You are writing multiple language applications, such as C++ DLL's accessed by Visual Basic applications.
Один из _bstr_t
Конструкторы позволяют просто присоединиться к существующим BSTR
так что вы можете иметь исключение, которое вы хотите от CString::AllocSysString
когда BSTR
распределение не удается.
// _bstr_t simply attaches to BSTR, doesn't reallocate it
interface->CallMethod( _bstr_t(sourceString.AllocSysString(), false) );
_bstr_t
Документация конструктора гласит:
_bstr_t(
BSTR bstr,
bool fCopy
);
fCopy
Если ложь, тоbstr
Аргумент присоединяется к новому объекту без копирования путем вызоваSysAllocString
,
С другой стороны, CComBSTR
конструктор, похоже, не имеет соответствующей подписи; хотя это может быть использовано также, если BSTR
Исключение из-за сбоя при распределении на самом деле не требуется, как отметил Phil Booth в своем ответе