Какой код лучше для преобразования параметров BSTR в ANSI в C / C ++? - PullRequest
3 голосов
/ 23 февраля 2009

До сих пор я обнаружил, что могу конвертировать входящие BSTR в ANSI двумя (многими?) Способами, и мне любопытно узнать, является ли один «лучше», чем другой, в отношении скорости / эффективности и т. Д.

То, что я использовал некоторое время, - это использование макросов USES_CONVERSION и W2A, например

BSTR __stdcall F(BSTR p1, BSTR p2 ) {
    USES_CONVERSION;

    LPSTR sNum1 = W2A( p1 );
    LPSTR sNum2 = W2A( p2 );

Однако недавно я столкнулся с другой техникой:

BSTR __stdcall F(BSTR p1, BSTR p2 ) {
    long amt = wcstombs( NULL, p1, 1 );
    sNum1 = (char *) malloc( amt ); 
    wcstombs( sNum1, p1, amt );
    *(sNum1 + amt) = '\0';

    amt = wcstombs( NULL, p2, 1 );
    sNum2 = (char *) malloc( amt ); 
    wcstombs( sNum2, p2, amt );
    *(sNum2 + amt) = '\0';

Теперь я даю вам слово, оно более словесное и имеет два вызова wcstombs, но, насколько я знаю, макросы USES_CONVERSION и W2A могут скрывать всевозможные забавы и игры.

Какой код эффективнее / быстрее? Или есть другой метод, который я мог бы использовать, чтобы сделать работу лучше?

Ответы [ 4 ]

6 голосов
/ 23 февраля 2009

С MSDN :

[...] Рекомендуемый способ преобразования в и из строк BSTR - использовать класс CComBSTR . Чтобы преобразовать в BSTR, передайте существующую строку в конструктор CComBSTR. Для конвертации из BSTR используйте COLE2 [C] DestinationType [EX], например COLE2T.

Со страницы CComBSTR:

[...] Класс CComBSTR предоставляет ряд членов (конструкторов, операторов присваивания и операторов сравнения), которые принимают в качестве аргументов строки ANSI или Unicode. Версии ANSI этих функций менее эффективны, чем их аналоги Unicode, потому что временные строки Unicode часто создаются внутри. Для эффективности используйте версии Unicode, где это возможно.

3 голосов
/ 04 марта 2010

Обратите внимание на одобренный ответ Ника, который, хотя и правильно, разделяет ту же проблему, что и в документации MSDN, описывающей макросы.

Проблема в том, что некоторые макросы, такие как перечисленные @Nick - COLE2A, на самом деле не существуют.

Тем не менее, ниже на странице MSDN есть текст, который подсказывает вам этот факт и поможет вам найти правильный макрос!

Текст приведен в таблице под следующим текстом:

Существует несколько важных различий между старыми макросами преобразования строк и новыми классами преобразования строк:

В столбце Новые классы преобразования ATL 7.0.

Что говорит:

OLE всегда эквивалентно W

Итак, макрос в примере @ Ника на самом деле CW2A

3 голосов
/ 23 февраля 2009

Примечание:

Если вы используете макросы ATL, например: COLE2 [C] DestinationType [Ex] (что вам, вероятно, следует), не забудьте использовать версии «C», а не неконстантные версии, как вы написали. Они могут быть эквивалентны для явных преобразований BSTR-> ASCII (т. Е. COLE2A), но для преобразований, где фактическое преобразование не требуется (например, COLE2T при компиляции для UNICODE), версии 'C' могут расширяться до noops, тогда как Версии -C будут по-прежнему копироваться, если исходная строка является константой (поскольку вы выражаете, что вам нужно, чтобы результирующая строка была неконстантной).

Также примечание:

Новые макросы ATL7 не всегда требуют USES_CONVERSION, однако они выделяют временные объекты r-значения, тогда как старые макросы используют _alloca. Это может или не может быть важным, в зависимости от вашего использования (например, НЕ используйте старые макросы в цикле, который выполняется большое количество раз, вы можете выкинуть стек таким образом).

1 голос
/ 24 февраля 2009

Прошло много времени с тех пор, как я что-то делал с COM или BSTR, но я предлагаю прекратить относиться к BSTR как к чему-то особенному. Обращайтесь с ними как с указателем на строку широких символов с нулем в конце ... если вы это сделаете, может быть проще преобразовать их в ANSI. check Полное руководство Эрика по семантике BSTR ...

...