【问题标题】:Mapping COM VARIANT Types to actual types using a map使用映射将 COM VARIANT 类型映射到实际类型
【发布时间】:2010-09-01 22:50:36
【问题描述】:

我正在为一个 COM 对象编写一个 COM 包装器,它从客户端发送不同类型的值,并希望将 Map 中的这些类型映射到它们的实际 C++ 类型,例如 VT_BSTR 到 wstring 等。

我正在考虑定义所有 COM Variant 类型的枚举,然后使用映射将该 Enum 作为键和包含检索到的值的实际类型,但是我遇到了我似乎无法找到的问题放置在我的地图中的全局类型,我可以将其转换为字符串或双精度或交给我放置在地图中的任何内容。

也许我对如何做到这一点的想法是完全错误的,请指教?

我在想一个 void 指针,但是编译器似乎不喜欢我的强制转换:

(示例)

    enum Type
    {
        VT_INTEGER=0,
        VT_DBL=1

    };


    map<Type, void*> typemap;
    typedef pair<Type, void*> m_typepair;
    typemap.insert( m_typepair(VT_INTEGER, 0));
    typemap.insert( m_typepair(VT_DBL, (double)2.5));  // it does not like this cast

    map<Type, void*>::iterator m_typeiter;

迭代这个映射可能需要在里面添加一个switch语句来找到正确的类型,我不确定是否有更好的方法?

【问题讨论】:

    标签: c++ com map variant


    【解决方案1】:

    不确定您要做什么,这听起来肯定是错误的。您从客户端获得的 VARIANT 需要转换为您知道如何处理的类型。这很容易做到,只需调用 VariantToXxxx() 函数即可。例如,如果要获取字符串,请使用 VariantToString()。

    已经有几个可用的 C++ 包装器类使这更容易。 _variant_t,CComVariant,COleVariant。他们都做同样的事情,只是不同的#include 文件。 _variant_t 是一个很好的选择,因为它不会将您绑定到 MFC 或 ATL。除非你已经在使用它们。他们的 ChangeType() 方法进行了转换。内存管理是自动的。

    【讨论】:

      【解决方案2】:

      我通常使用模板专业化来完成这类任务。我有一个模板函数,可以将变体类型转换为 C++ 类型,如下所示:

      template <typename T>
      T variantToCpp(const Variant&);
      
      template <>
      int variantToCpp<int>(const Variant& v)
      {
        // Check that v really contains an int, if not, you can silently fail or throw an exception
        // Get and return the int
      }
      
      template <>
      std::wstring variantToCpp<std::wstring>(const Variant& v)
      {
        // Check that v really contains a string, if not, you can silently fail or throw an exception
        // Get and return the string
      }
      
      // etc. for each C++ type
      
      // Usage
      int i = variantToCpp<int>(someVariantIGotViaCOM);
      

      通过这种方式,您可以获得从 Variant 到 C++ 类型的恒定时间转换。另请注意,默认模板化函数没有主体 - 如果有人尝试对非专业类型使用转换,它将导致链接器错误(在大多数编译器上)。

      同样,您可以将 C++ 类型转换为 Variant:

      template <typename T>
      Variant cppToVariant(T);
      
      template <>
      Variant cppToVariant<int>(int val)
      {
        // Convert to variant and return it
      }
      
      // etc. for each type
      
      // Usage:
      int i = 10;
      Variant var = cppToVariant(i);  // You don't even need to explicitly specify the type here, the compiler deduces it
      

      如果您坚持使用映射和大量 if 进行这种转换,您可以使用您的 void* 指针,您只需使用指向类型的指针对其进行初始化:

      int *myInteger = new int; *myInteger = 42;
      double *myDouble = new double; *myDouble = 42;
      typemap.insert( m_typepair(VT_INTEGER, myInteger));
      typemap.insert( m_typepair(VT_DBL, myDouble));
      // Don't forget to free them when you clear the map
      

      如果您对上述任何解决方案都不满意,boost::any 可能值得一看。

      【讨论】:

        【解决方案3】:

        你知道_variant_t 吗?你可能正在重新发明轮子。它具有所有相关的构造函数和重载赋值。 IE。 _variant_t var = 0.0 按预期工作 (VT_R8)

        【讨论】:

          猜你喜欢
          • 2020-05-16
          • 1970-01-01
          • 1970-01-01
          • 2020-03-07
          • 2016-04-15
          • 2015-02-24
          • 1970-01-01
          • 1970-01-01
          • 2018-08-01
          相关资源
          最近更新 更多