使用映射将 COM VARIANT 类型映射到实际类型

发布于 2024-09-17 05:27:11 字数 717 浏览 7 评论 0原文

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

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

也许我的想法是完全错误的,请指教?

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

I am writing a COM wrapper for a COM object that sends different types of values from a client and want to map these types in a Map to their actual C++ type, such as VT_BSTR to a wstring, etc.

I was thinking of defining an enumuration of all COM Variant types and then using a map to have that Enum as the key and the actual type containing the retrieved value, however I'm running into the issue that I cannot seem to find a global type to put in my map that I can cast to a string or double or whatever is handed to me to place in the map.

Perhaps my thinking of how to do this is entirely wrong, please advice?

I was thinking of a void pointer, however it seems the compiler doesn't like my casts:

(example)

    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;

Iterating this map would probably need a switch statement inside to find the right type, I'm not sure if there is a better way?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

九厘米的零° 2024-09-24 05:27:21

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

Are you aware of _variant_t ? You might be reinventing the wheel. It has all the relevant constrcutors and overloaded assignment. I.e. _variant_t var = 0.0 works as expected (VT_R8)

∝单色的世界 2024-09-24 05:27:19

我通常使用模板专门化来完成此类任务。我有一个模板函数,可以从变体类型转换为 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);

通过这种方式,您可以实现从变体类型到 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 可能值得一看。

I usually use template specialization for this kind of tasks. I have a template function that converts from a variant type to a C++ type that looks like this:

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

This way you get a constant-time conversion from a Variant to a C++ type. Also note that the default templated function has no body - it will cause a linker error (on most compilers) if someone tries to use a conversion for an unspecialized type.

Similarly you can do the conversion from a C++ type to a 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 you insist on using a map and tons of ifs for this kind of conversion, you can use your void* pointer, you just have to initialize it with a pointer to the type:

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

If you aren't satisfied with any of the above solutions, boost::any might be worth looking at.

探春 2024-09-24 05:27:18

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

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

Not sure what you're trying to do, it certainly sounds wrong. A VARIANT you get from a client needs to be converted to the type that you know how to deal with. That's easy to do, just call the VariantToXxxx() function. For example, use VariantToString() if you want to get a string.

There are several C++ wrapper classes already available that make this easier. _variant_t, CComVariant, COleVariant. They all do the same thing, just different #include files. _variant_t is a good one because it doesn't tie you into either MFC or ATL. Unless you are already using them. Their ChangeType() method makes the conversion. Memory management is automatic.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文