Как лучше конвертировать 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 в своем ответе

Другие вопросы по тегам