web-dev-qa-db-fra.com

BSTR à std :: string (std :: wstring) et vice versa

Lorsque vous utilisez COM en C++, les chaînes sont généralement du type de données BSTR. Quelqu'un peut utiliser BSTR wrapper comme CComBSTR ou CString de MS. Mais comme je ne peux pas utiliser ATL ou MFC dans le compilateur MinGW, existe-t-il un extrait de code standard permettant de convertir BSTR en std::string (ou std::wstring) et vice versa?

Existe-t-il également des wrappers non-MS pour BSTR similaires à CComBSTR?

Mise à jour

Merci à tous ceux qui m'ont aidé de quelque manière que ce soit! Tout simplement parce que personne n’a résolu le problème de la conversion entre BSTR et std::string, Je voudrais donner ici quelques indices sur la manière de le faire.

Vous trouverez ci-dessous les fonctions que j’utilise pour convertir BSTR en std::string et std::string à BSTR respectivement:

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;
}
61
ezpresso

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());

Doc refs:

  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()
86
ildjarn

Tu pourrais aussi faire ça

#include <comdef.h>

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

ou std :: string si vous préférez

10
Anders

Passez simplement le BSTR directement au constructeur wstring, il est compatible avec un wchar_t *:

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

La conversion de BSTR en std :: string nécessite d'abord une conversion en char *. Cela entraîne des pertes, car BSTR stocke une chaîne Unicode codée en utf-16. Sauf si vous voulez encoder dans utf-8. Vous trouverez des méthodes d'assistance pour le faire, ainsi que la manipulation de la chaîne résultante, dans la bibliothèque ICU.

3
Hans Passant

Il existe une classe c ++ appelée _bstr_t. Il a des méthodes utiles et une collection d'opérateurs surchargés.

Par exemple, vous pouvez facilement assigner un const wchar_t * Ou un const char * En faisant juste _bstr_t bstr = L"My string";. Vous pourrez ensuite le reconvertir en faisant const wchar_t * s = bstr.operator const wchar_t *();. Vous pouvez même le reconvertir en un caractère normal const char * c = bstr.operator char *(); Vous pouvez ensuite simplement utiliser le const wchar_t * Ou le const char * Pour initialiser un nouveau std::wstring Oe std::string.

3
user2074102