【问题标题】:Changing type of CComVariant variable doesn't work inside ATL method更改 CComVariant 变量的类型在 ATL 方法中不起作用
【发布时间】:2015-01-16 08:26:57
【问题描述】:

我正在尝试构建一个 ATL COM 类,它具有以下方法:

STDMETHODIMP CTestClass::TestMethod(VARIANT VarIn, VARIANT_BOOL* bRes)
{
    //VarIn is of type VT_INT

    CComVariant var(VarIn);
    var.ChangeType(VT_UI8); //doesn't work, HRESULT return value reports type mismatch
    ULONGLONG ullVal = var.ullVal; //wrong value is assigned
    *bRes = VARIANT_TRUE;
    return S_OK;
}

问题在于CComVariant 实例的类型在方法内部 没有改变。例如,如果我将基于 int 的值 123 传递给上述方法,则不会执行到 VT_UI8 的类型转换。

但是,如果 CComVariant 类用于独立函数中,则通过 ChangeType() 方法更改类型完美无缺:

void Function()
{
    CComVariant var(123);
    var.ChangeType(VT_UI8); //ok
    ULONGLONG ullVal = var.ullVal; //correct value is assigned
}

有什么我忽略的吗?谢谢。

【问题讨论】:

  • 您按值传递它。所以当然调用者的变体不会改变。
  • @HansPassant 我不想将变体传递回调用者,这就是我按值传递它的原因。相反,我想在 ATL 方法中更改 CComVariant 实例的类型。这将允许我将其值分配给一个新的 ULONGLONG 变量。
  • Q 缺少细节。如果您想在返回后转换值,请参阅 Hans 上面的评论。如果您有转换失败,您必须提及输入变量值并检查ChangeType 调用返回的值。

标签: c++ com atl


【解决方案1】:

那么您的测试代码应该是这样的:

CComVariant v;
v.vt = VT_INT;
v.intVal = 123;
const HRESULT n = v.ChangeType(VT_UI8); // 0x80020005 DISP_E_TYPEMISMATCH Type mismatch.

ChangeTypeVariantChangeType API 支持,它...

...处理基本类型之间的强制转换(包括数字到字符串和字符串到数字的强制转换)。

然而,问题是定义了太多的“基本”类型,有些比其他类型“更基本”。比如VT_I4就比VT_INT好:

CComVariant v;
v.vt = VT_INT;
v.intVal = 123;
const HRESULT n1 = v.ChangeType(VT_UI8); // 0x80020005 DISP_E_TYPEMISMATCH Type mismatch.
v.vt = VT_I4;
const HRESULT n2 = v.ChangeType(VT_UI8); // S_OK
ULONGLONG n = v.ullVal; // 123

也就是说,API 转换似乎不接受 VT_INT。首选此列表顶部的类型会更安全:

enum VARENUM
    {
        VT_EMPTY    = 0,
        VT_NULL = 1,
        VT_I2   = 2,
        VT_I4   = 3,
        VT_R4   = 4,
        VT_R8   = 5,
        VT_CY   = 6,
        VT_DATE = 7,
        VT_BSTR = 8,
        VT_DISPATCH = 9,
        VT_ERROR    = 10,
        VT_BOOL = 11,
        VT_VARIANT  = 12,
        VT_UNKNOWN  = 13,
        VT_DECIMAL  = 14,
        VT_I1   = 16,
        VT_UI1  = 17,
        VT_UI2  = 18,
        VT_UI4  = 19,
        VT_I8   = 20,
        VT_UI8  = 21,
        // *** Cut off line ***
        VT_INT  = 22,
        VT_UINT = 23,

进一步阅读:

【讨论】:

  • 谢谢,这是有道理的。这是否意味着在处理 VT_INTVT_UINT 类型时,我总是不得不求助于手动转换例程?
  • 您见证了标准 API 不接受 VT_INT,因此避免这种类型或自行实施转换应该是一个很好的信号。
猜你喜欢
  • 1970-01-01
  • 2015-03-20
  • 2011-12-20
  • 1970-01-01
  • 2011-03-10
  • 1970-01-01
  • 2015-01-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多