Windows平台上有一些遗留的COM代码,想要移植到Linux,但__uuidof()不能在gcc下使用
对于大多数情况,可以使用以下代码解决它。
#define __uuidof(T) IID_ ##T
但在某些情况下,它无法正常工作,例如,
template <class T>
HRESULT QueryInterface(IUnknown* p, T** ppv)
{
return p->QueryInterface(__uuidof(T), (void**)ppv);
}
所以我想实现一个模板函数让它工作,比如,
template <class T>
GUID __uuidof()
{
return IID_ ##typeof(T);
}
如何实现它并让它与一般解决方案完全一致?无法保证每个接口定义中都存在静态成员_IID。
感谢。
答案 0 :(得分:0)
根据帖子How can I define an UUID for a class, and use __uuidof, in the same way for g++ and Visual C++?虽然我无法在该帖子中成功编译代码,但是在遵循其中提到的想法之后,这个想法很好,并且可以编译并运行良好的示例代码用于解决gcc下的__uuid
#include <iostream>
#include <memory.h>
#include <assert.h>
using namespace std;
#define nybble_from_hex(c) ((c>='0'&&c<='9')?(c-'0'):((c>='a'&&c<='f')?(c-'a' + 10):((c>='A'&&c<='F')?(c-'A' + 10):0)))
#define byte_from_hex(c1, c2) ((nybble_from_hex(c1)<<4)|nybble_from_hex(c2))
typedef struct _GUID {
unsigned long Data1;
unsigned short Data2;
unsigned short Data3;
unsigned char Data4[ 8 ];
} GUID;
static GUID GUID_NULL = {0, 0, 0, {0, 0, 0, 0, 0, 0, 0 ,0}};
#ifndef _REFGUID_DEFINED
#define _REFGUID_DEFINED
#ifdef __cplusplus
#define REFGUID const GUID &
#else
#define REFGUID const GUID * __MIDL_CONST
#endif
#endif
__inline int IsEqualGUID(REFGUID rguid1, REFGUID rguid2)
{
return !memcmp(&rguid1, &rguid2, sizeof(GUID));
}
#ifdef __cplusplus
__inline bool operator==(REFGUID guidOne, REFGUID guidOther)
{
return !!IsEqualGUID(guidOne,guidOther);
}
__inline bool operator!=(REFGUID guidOne, REFGUID guidOther)
{
return !(guidOne == guidOther);
}
#endif
struct Initializable : public GUID
{
explicit
Initializable(char const (&spec)[37])
: GUID()
{
for (int i = 0; i < 8; ++i)
{
Data1 = (Data1 << 4) | nybble_from_hex(spec[i]);
}
assert(spec[8] == '-');
for (int i = 9; i < 13; ++i)
{
Data2 = (Data2 << 4) | nybble_from_hex(spec[i]);
}
assert(spec[13] == '-');
for (int i = 14; i < 18; ++i)
{
Data3 = (Data3 << 4) | nybble_from_hex(spec[i]);
}
assert(spec[18] == '-');
for (int i = 19; i < 23; i += 2)
{
Data4[(i - 19) / 2] = (nybble_from_hex(spec[i])<<4) | nybble_from_hex(spec[i+1]);
}
assert(spec[23] == '-');
for (int i = 24; i < 36; i += 2)
{
Data4[2 + (i - 24) / 2] = (nybble_from_hex(spec[i]) << 4) | nybble_from_hex(spec[i + 1]);
}
}
};
template<class T>
inline
auto __my_uuidof()
-> GUID const &
{
return GUID_NULL;
}
#define CPPX_GNUC_UUID_FOR( name, spec ) \
template<> \
inline \
auto __my_uuidof<name>() \
-> GUID const& \
{ \
using ::operator"" _uuid; \
static GUID the_uuid = spec ## _uuid; \
\
return the_uuid; \
} \
\
template<> \
inline \
auto __my_uuidof<name*>() \
-> GUID const& \
{ return __my_uuidof<name>(); } \
\
static_assert( true, "" )
auto operator"" _uuid(char const* const s, size_t const size)
-> GUID
{
return Initializable(reinterpret_cast<char const (&)[37]>(*s));
}
#define CPPX_UUID_FOR CPPX_GNUC_UUID_FOR
#define __uuid(T) __my_uuidof<T>()
struct Foo {};
CPPX_UUID_FOR(Foo, "dbe41a75-d5da-402a-aff7-cd347877ec00");
Foo foo;
template <class T>
void QueryInterface(T** p)
{
if (p == NULL)
return;
GUID guid = "dbe41a75-d5da-402a-aff7-cd347877ec00"_uuid;
if (__uuid(T) == guid)
{
*p = &foo;
}
else
{
*p = NULL;
}
return;
}
int main()
{
Foo* p = NULL;
QueryInterface(&p);
cout << "p: " << p << ", &foo: " << &foo << endl;
return 0;
}
保存到uuidtest.cpp,我使用g ++ - 7成功编译(其他gcc与c ++ 11/14支持也可以正常工作),运行良好:
g++-7 uuidtest.cpp -o uuidtest
./uuidtest
p: 0x6021c0, &foo: 0x6021c0
答案 1 :(得分:-2)
也许typeid会起作用
否则, 您可以使用reinterpret_cast。
For exemple here we have the class A;
A * ex;
ex = reinterpret_cast<A>(*pv);
if (ex == NULL)
{
//Do some stuff
//this means **ex** isn't a A class
}
它适用于从A继承的所有类。