0

我正在为 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 语句来找到正确的类型,我不确定是否有更好的方法?

4

3 回答 3

1

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

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

于 2010-09-01T14:48:44.037 回答
0

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

于 2010-09-01T14:50:36.127 回答
0

我通常对这类任务使用模板专业化。我有一个模板函数,可以从变体类型转换为 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

如果您坚持使用映射和大量 ifs 进行这种转换,则可以使用 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可能值得一看。

于 2010-09-01T14:17:25.070 回答