BSTR в std :: string (std :: wstring) и наоборот - PullRequest
59 голосов
/ 09 июня 2011

При работе с COM в C ++ строки обычно имеют тип данных BSTR. Кто-то может использовать BSTR обертку, как CComBSTR или MS CString. Но поскольку я не могу использовать ATL или MFC в компиляторе MinGW, существует ли стандартный фрагмент кода для преобразования BSTR в std::string (или std::wstring) и наоборот?

Существуют ли также обертки не-MS для BSTR, подобные CComBSTR?

Обновление

Спасибо всем, кто помог мне в любом случае! Просто потому, что никто не обратился к вопросу о преобразовании между BSTR и std::string, я хотел бы привести здесь некоторые подсказки о том, как это сделать.

Ниже приведены функции, которые я использую для преобразования BSTR в std::string и std::string в BSTR соответственно:

std::string ConvertBSTRToMBS(BSTR bstr)
{
    int wslen = ::SysStringLen(bstr);
    return ConvertWCSToMBS((wchar_t*)bstr, wslen);
}

std::string ConvertWCSToMBS(const wchar_t* pstr, long wslen)
{
    int len = ::WideCharToMultiByte(CP_ACP, 0, pstr, wslen, NULL, 0, NULL, NULL);

    std::string dblstr(len, '\0');
    len = ::WideCharToMultiByte(CP_ACP, 0 /* no flags */,
                                pstr, wslen /* not necessary NULL-terminated */,
                                &dblstr[0], len,
                                NULL, NULL /* no default char */);

    return dblstr;
}

BSTR ConvertMBSToBSTR(const std::string& str)
{
    int wslen = ::MultiByteToWideChar(CP_ACP, 0 /* no flags */,
                                      str.data(), str.length(),
                                      NULL, 0);

    BSTR wsdata = ::SysAllocStringLen(NULL, wslen);
    ::MultiByteToWideChar(CP_ACP, 0 /* no flags */,
                          str.data(), str.length(),
                          wsdata, wslen);
    return wsdata;
}

Ответы [ 4 ]

84 голосов
/ 09 июня 2011

BSTR до std::wstring:

// given BSTR bs
assert(bs != nullptr);
std::wstring ws(bs, SysStringLen(bs));


std::wstring до BSTR:

// given std::wstring ws
assert(!ws.empty());
BSTR bs = SysAllocStringLen(ws.data(), ws.size());

Документы для справки:

  1. std::basic_string<typename CharT>::basic_string(const CharT*, size_type)
  2. std::basic_string<>::empty() const
  3. std::basic_string<>::data() const
  4. std::basic_string<>::size() const
  5. SysStringLen()
  6. SysAllocStringLen()
9 голосов
/ 15 августа 2014

Вы также можете сделать это

#include <comdef.h>

BSTR bs = SysAllocString("Hello");
std::wstring myString = _bstr_t(bs, false); // will take over ownership, so no need to free

или std :: string, если вы предпочитаете

3 голосов
/ 27 июня 2017

Существует класс c ++ с именем _bstr_t. Имеет полезные методы и коллекцию перегруженных операторов.

Например, вы можете легко присвоить из const wchar_t * или const char *, просто выполнив _bstr_t bstr = L"My string"; Затем вы можете преобразовать его обратно, выполнив const wchar_t * s = bstr.operator const wchar_t *();. Вы даже можете преобразовать его обратно в обычный символ const char * c = bstr.operator char *(); Затем вы можете просто использовать const wchar_t * или const char * для инициализации нового std::wstring oe std::string.

3 голосов
/ 09 июня 2011

Просто передайте BSTR непосредственно конструктору wstring, он совместим с wchar_t *:

BSTR btest = SysAllocString(L"Test");
assert(btest != NULL);
std::wstring wtest(btest);
assert(0 == wcscmp(wtest.c_str(), btest));

Преобразование BSTR в std :: string требует сначала преобразования в char *. Это потеря, поскольку BSTR хранит строку Unicode в кодировке utf-16. Если только вы не хотите кодировать в utf-8. Вы найдете вспомогательные методы для этого, а также манипулируете полученной строкой в ​​библиотеке ICU.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...