Как лучше всего преобразовать CString в BSTR, чтобы передать его в качестве параметра "in" в метод COM? - PullRequest
8 голосов
/ 18 января 2010

Мне нужно преобразовать экземпляр CString в правильно распределенный BSTR и передать этот BSTR в метод COM. Чтобы иметь код, который компилируется и работает одинаково для ANSI и Unicode, я использую CString::AllocSysString() для преобразования любого формата CString в BSTR Unicode.

Поскольку никто не владеет возвращенным BSTR, мне нужно позаботиться о нем и освободить его после того, как вызов будет выполнен наиболее безопасным для исключения способом и с как можно меньшим количеством кода.

В настоящее время я использую ATL::CComBSTR для управления жизненным циклом:

 ATL::CComBSTR converted;
 converted.Attach( sourceString.AllocSysString() ); //simply attaches to BSTR, doesn't reallocate it
 interface->CallMethod( converted );

что мне здесь не нравится, так это то, что мне нужны два отдельных оператора, чтобы просто построить ATL::CComBSTR, привязанный к результату преобразования.

Есть ли лучший способ выполнить ту же задачу?

Ответы [ 3 ]

15 голосов
/ 18 января 2010

CComBSTR имеет перегруженные конструкторы для char* и wchar_t*, которые выполняют вызов SysAllocString() от вашего имени. Так что явное выделение в вашем фрагменте кода на самом деле не нужно. Следующее будет работать так же хорошо:

ATL::CComBSTR converted = sourceString;
interface->CallMethod(converted);

Кроме того, если вам не нужно использовать преобразованный BSTR в другом месте кода, вы можете выполнить конструирование объекта на месте при вызове метода, например:

interface->CallMethod(ATL::CComBSTR(sourceString));

То же самое относится к классу _bstr_t, который можно использовать вместо CComBSTR, если вы не хотите зависеть от ATL.

2 голосов
/ 08 февраля 2012

Одним из запутанных аспектов программирования 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.
1 голос
/ 23 января 2013

Один из конструкторов _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
Если false, аргумент bstr присоединяется к новому объекту без копированиявызов SysAllocString.

С другой стороны, CComBSTR конструктор не имеет соответствующей подписи;хотя его можно использовать и в том случае, если исключение BSTR при распределении не является действительно необходимым, как упомянуто Филом Бутом в его ответе .

...