首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何将CComVariant bstr转换为CString

如何将CComVariant bstr转换为CString
EN

Stack Overflow用户
提问于 2017-08-03 12:24:53
回答 3查看 2.8K关注 0票数 0

我是C++的新手,我接手了一个COM项目来解决一些问题。我正在处理的当前问题是处理UTF8字符串。我有一段代码:

代码语言:javascript
运行
复制
// CString strValue;
CStringW strValue; 
CComVariant* val = &(*result)[i].minValue;
switch (val->vt)
{
case VT_BSTR:   
    //strValue = OLE2CA(val->bstrVal);
    strValue = OLE2W(val->bstrVal); // Works
    (*result)[i].name = strValue; // Works
    (*result)[i].expression = "[" + fieldName + "] = \"" + strValue + "\""; // fails
    break;
case VT_R8:     
    //strValue.Format("%g", val->dblVal);
    strValue.Format(L"%g", val->dblVal); // Works
    (*result)[i].name = strValue; // Works
    (*result)[i].expression = "[" + fieldName + "] = " + strValue; // fails
    break;
case VT_I4:     
    //strValue.Format("%i", val->lVal);
    strValue.Format(L"%i", val->lVal); // Works
    (*result)[i].name = strValue; // Works
    (*result)[i].expression = "[" + fieldName + "] = " + strValue; // fails
    break;
}

struct CategoriesData
{
    public:
    CComVariant minValue;
    CComVariant maxValue;
    //CString expression;
    CStringW expression;
    //CString name;
    CStringW name;
    tkCategoryValue valueType;
    int classificationField;
    bool skip;
};

问题在于这一行strValue = OLE2CA(val->bstrVal);,当val->bstrVal是一个unicode字符串时,像这个俄文文本Воздух strValue被转换成?????

我试过几次接近并搜索互联网,但无法让strValue成为ВоздухCString可以包含这种文本吗?还是应该更改为另一种类型?是哪一个?

minValue可以是VT_BSTR、VT_R8或VT_I4。

到目前为止,我尝试了以下几种选择:

代码语言:javascript
运行
复制
strValue = val->bstrVal;
strValue = Utility::ConvertFromUtf8(val->bstrVal);
strValue = Utility::ConvertToUtf8(val->bstrVal);
temp = Utility::ConvertBSTRToLPSTR(val->bstrVal);
strValue = W2BSTR(Utility::ConvertFromUtf8(temp));
strValue = W2BSTR(val->bstrVal);                
strValue = CW2A(val->bstrVal);
strValue = (CString)val->bstrVal;
strValue = Utility::ConvertToUtf8(OLE2W(val->bstrVal));

编辑助手函数的代码:

代码语言:javascript
运行
复制
CStringA ConvertToUtf8(CStringW unicode) {
    USES_CONVERSION;
    CStringA utf8 = CW2A(unicode, CP_UTF8);
    return utf8;
}

CStringW ConvertFromUtf8(CStringA utf8) {
    USES_CONVERSION;
    CStringW unicode = CA2W(utf8, CP_UTF8);
    return unicode;
}

char* ConvertBSTRToLPSTR (BSTR bstrIn)
{
  LPSTR pszOut = NULL;
  if (bstrIn != NULL)
  {
    int nInputStrLen = SysStringLen (bstrIn);

    // Double NULL Termination
    int nOutputStrLen = WideCharToMultiByte(CP_ACP, 0, bstrIn, nInputStrLen, NULL, 0, 0, 0) + 2; 
    pszOut = new char [nOutputStrLen];

    if (pszOut)
    {
      memset (pszOut, 0x00, sizeof (char)*nOutputStrLen);
      WideCharToMultiByte (CP_ACP, 0, bstrIn, nInputStrLen, pszOut, nOutputStrLen, 0, 0);
    }
  }
  return pszOut;
}

Edit2我添加了完整的开关语句。当我将strValue从CString改为CStringW时,会得到其他情况下的错误,比如strValue.Format("%g", val->dblVal);,如何解决这个问题?

Edit3 I已经修复了一个类似的问题,但这是转换为VARIANT而不是从:

代码语言:javascript
运行
复制
    val->vt = VT_BSTR;
    const char* v = DBFReadStringAttribute(_dbfHandle, _rows[RowIndex].oldIndex, _fields[i]->oldIndex);
    // Old code, not unicode ready:
    //WCHAR *buffer = Utility::StringToWideChar(v);
    //val->bstrVal = W2BSTR(buffer);
    //delete[] buffer;              
    // New code, unicode friendly:
    val->bstrVal = W2BSTR(Utility::ConvertFromUtf8(v)); 

Edit4,感谢到目前为止所提供的所有帮助,我成功地做了一些更改。我在这篇文章中更新了我的初始代码,并添加了函数的所有代码。我现在被困在这句话里:

代码语言:javascript
运行
复制
 (*result)[i].expression = "[" + fieldName + "] = \"" + strValue + "\"";    

我不能连接CStringW值。

更多的背景信息:这个函数是MapWinGIS的一部分,它是一个开源的地理信息系统应用程序,在这里你可以显示地图(Shapefile)。这些地图有属性数据。这些数据以DBase IV格式存储,可以保存unicode/UTF-8文本。我已经做了一个修复(参见Edit3),以便在网格视图中正确地显示该文本。我现在正在挣扎的函数是对数据进行分类(分组),例如给相似的值以相同的颜色。这个类别有一个名称和一个表达式。稍后将解析此表达式以执行实际分组。例如,我有一个有状态的地图,我想给每个州一个不同的颜色。正如前面提到的,我是C++的新手,而且真的超出了我的舒适范围。我真的很感激你给我的一切帮助。我希望你能再帮我一次。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2017-08-03 14:22:35

BSTRs“自然”存储Unicode UTF-16长度-前缀字符串,尽管您可以“拉伸”BSTR并使用它存储一个更通用的前缀字节序列(但我不喜欢这种用法)。

(有关BSTR的更多细节,您会发现这篇由Eric Lippert撰写的博客文章非常有趣。)

所以,我正在考虑BSTR的正常用法,它存储长度前缀UTF-16字符串。

如果要将存储在BSTR中的UTF-16字符串转换为UTF-8字符串,可以使用带有CP_UTF8标志的WideCharToMultiByte Win32 API (参见这篇MSDN杂志的文章获取详细信息和GitHub上的可重用代码)。

可以将目标UTF-8字符串存储在std::string类的实例中。

P.S.如果您想对UTF-16使用CStringW,对于UTF-8字符串使用CStringA,对于UTF-16/8转换使用ATL CW2A助手,请注意代码中不需要USES_CONVERSION宏;您可以将const& (const引用)的输入字符串作为良好的代码卫生:

代码语言:javascript
运行
复制
CStringA Utf8FromUtf16(const CStringW &utf16) {
    CStringA utf8 = CW2A(utf16, CP_UTF8);
    return utf8;
}

RE编辑2

尝试strValue.Format(L"%g",...CStringWL前缀为CStringW::Format生成一个Unicode 16字符串文本。

RE编辑4

我在注释中对此做出了答复,但为了完整起见,要将字符串文本与CStringW实例连接起来,可以考虑使用L"...":来装饰这些文字--这定义了一个Unicode UTF-16字符串文字,即wchar_t-based,并且可以很好地处理CStringW对象。

代码语言:javascript
运行
复制
(*result)[i].expression = L"[" + fieldName + L"] = \"" + strValue + L"\"";    
票数 2
EN

Stack Overflow用户

发布于 2017-08-03 12:33:35

如果不将项目转换为Unicode感知的应用程序,则无法获得始终工作的版本。

换句话说,要支持所有可能在BSTR中分离的字符,您需要一个Unicode CString (CStringW)。

您可以继续使用MBCS版本,但在这种情况下,您仍然需要处理Unicode。在这里使用CStringW可能是一种选择。

转换为UTF-8是用WideCHarToMultiByte完成的。

票数 1
EN

Stack Overflow用户

发布于 2021-09-29 05:38:45

如何:在各种字符串类型之间进行转换

https://learn.microsoft.com/en-us/cpp/text/how-to-convert-between-various-string-types

本主题演示如何将各种VisualC++字符串类型转换为其他字符串。涵盖的字符串类型包括char、wchar_t、_bstr_t、CComBSTR、CString、basic_string和System.String。在所有情况下,在转换为新类型时都会生成字符串的副本。对新字符串的任何更改都不会影响原始字符串,反之亦然。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45484130

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档