cexer

cexer
posts - 12, comments - 334, trackbacks - 0, articles - 0
  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

更好地仿真VC++关键字__uuidof

Posted on 2008-07-05 20:58 cexer 阅读(2661) 评论(8)  编辑 收藏 引用 所属分类: utility

转帖请注明出处 http://www.cppblog.com/cexer/archive/2008/07/05/55419.html

  世界上有个叫__uuidof的关键字。这是一个家喻户晓且其被广泛使用的关键字,几乎可以说,有COM程序员的地方,就有它 __uuidof的存在。其很好很强大的程度是人所共见的,夸张一点比喻:离开它的COM程序员,就像失去了点火器的火箭,虽然可以人工点火,但是不安全且无效率。

  不过很多人并不知道,这其实是一个编译器扩展关键字,提供了此关键字的仅VC一家别无它店。幸运的是,强大的C++让我们能够轻易仿真出这个关键字的大部分功能。

  网上能够找到一种仿真的方法,见许式伟:《仿真VC++提供的关键字__uuidof》。该方法的实现是:特化模板类的成员函数,然后运行时调用函数根据UUID字符串产生出UUID,由于是生成于运行时,所以它无可避免地有两个缺点:

  • 存在运行时消耗。
  • 无法作为非类型模板参数传递给模板。

  那些整天流着口水追求效率的C++程序员们,是不能忍受任何不必要的运行时消耗的。对于第二点,VC的关键字__uuidof取出来的UUID是能够作为非类型模板参数传递的,ATL中就大量地使用了这样的参数传递形式,所以目前的这种实现功能有限,仿真度还不够高。

  其实只要能让它能够编译期决定UUID的值,那么这两个问题就迎刃而解了。而这是肯定可以实现的,并且很简单。我曾经在自己写的一个COM库里实现过这样的方法,虽然那个库已经不知丢到哪里去了,不过那个方法还记得。

  解决的途径还是离不开模板特化。类的成员包括成员函数和成员变量,函数是运行时作用的,然而static const的成员变量可以是编译期就决定。所以解决的方法就在眼前了:特化模板的成员变量。

  以下是我的实现方法。

  先定义一个类模板,它有一个static const ,UUID类型的成员变量:

    template<typename T>   
struct _uuid_of_impl
{
static const UUID id;
};
template<typename T>
const UUID _uuid_of_impl<T>::id=GUID_NULL;

  有了这个简单的东西就好办了,只需要针对某个接口特它的成员变量就行了,如:

    template<>    
const UUID _uuid_of_impl<IUnknown>::id=IID_IUnknown;

template<>
const UUID _uuid_of_impl<IDispatch>::id=IID_IDispatch;



  然后我们就可以这样取得接口的UUID:

    IID IunknownID=_uuid_of_impl<IUnknown>::id;   
IID IdispatchID=_uuid_of_impl<IDispatch>::id;


  作为非类型模板参数传递:

    template<const IID* t_iid>   
struct __uuid_of_test
{
__uuid_of_test()
{}

void test()
{
t_iid;
}
};

__uuid_of_test<&(_uuid_of_impl<IDispatch>::id) > obj;


  不过现在这种实现还有一些问题,看以下代码:

    IID ITypelibID=_uuid_of_impl<ITypeLib>::id;


  注意我们并没有事先对模板__uuid_of_impl特化ITypeLib的版本。但是以上语句却能够编译通过,在运行时,__uuid_of_impl<ITypeLib>的值将会是错误的值GUID_NULL。这是因为,我们定义模板的时候,同时在模板外定义了模板的静态成员变量并赋值为GUID_NULL,所以没有用特化的方法定义UUID的接口,都将使用GUID_NULL这个通用值。这当然不是我们想要的。所以我们想在没有定义UUID的时候让编译器警告我们,要达到这样的效果只需要去掉上面那句:

    template<typename T>   
const UUID _uuid_of_impl<T>::id=GUID_NULL;


  现在再进行编译,编译器会告诉你,有一个无法解析的符号。根据编译器提供的相关信息,很容易就能确定问题所在。这样能够在编译期极大地减小安全隐患。

  最后加上我们定义的几个宏,这是最后的全部实现:

    template<typename T>   
struct _uuid_of_impl
{
static const UUID id;
};

#define uuid_of(x) _uuid_of_impl<x>::id
#define DEFINE_UUID(x,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \
template<> \
const UUID _uuid_of_impl<x>::id={l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}}


  用以下代码测试通过:

    struct ITest{};   

DEFINE_UUID(ITest,0x96289151,0xf059,0x4049,0x88,0x19,0x61,0xa6,0xe9,0x79,0xc,0xf1);

template<const IID* t_iid>
struct uuid_of_test
{
uuid_of_test(){}
};

int main()
{
IID xxxxID=uuid_of(ITest);
uuid_of_test<&(uuid_of(ITest))> obj;

return 0;
}


  需要注意的是DEFINE_UUID应该在实现文件(*.cpp,*.cxx,……)当中使用。到这里,仍有一些使用方法与VC的关键字是不一样的,所以仍没做到仿真度100%。不过我相信通过预处理元编程,能够相当程度地逼近它,只是我对预处理元编程不是很了解,所以就不在这里献丑了。

Feedback

# re: 更好地仿真VC++关键字__uuidof  回复  更多评论   

2008-07-06 02:15 by 放屁啊狗
我感觉ms的com快走向末路了,没有啥创新。ms走的就是自我封闭,自恋、自残的路线

# re: 更好地仿真VC++关键字__uuidof  回复  更多评论   

2008-07-06 05:33 by www.helpsoff.com.cn
好不容易在cppblog.com看到一篇真正的技术文章,不过看到的回复又实在让人如鲠在喉。“放屁阿狗”仁兄,君不知COM的技术和概念是多少现在所谓前沿技术和概念的基础,不知道是在睁眼说瞎话还是在这里说反话吸引眼球?

# re: 更好地仿真VC++关键字__uuidof  回复  更多评论   

2008-07-06 09:51 by 空明流转
@www.helpsoff.com.cn
这里技术文章也不少了。。。为什么叫真正的?
boost上有一个uuid的实现好像。
还有COM,这个东西确实很繁杂,但是概念上没什么问题,就是实现很拖沓。

# re: 更好地仿真VC++关键字__uuidof  回复  更多评论   

2008-07-06 09:55 by pang
你好 我是出版社的编辑,我看到你博客中的内容,感觉写的非常好,如果想把这些内容

和更多的人分享,可以和我联系,把这些东西写成书。
我的邮箱:books_522008@yahoo.com.cn
或者加我的MSN:pyq_19852008@hotmail.com

# re: 更好地仿真VC++关键字__uuidof  回复  更多评论   

2008-07-06 10:38 by toperray
看看ADOBE、firefox等等的基础技术吧,com消亡了?

没有,而且越来越多的被采用。

# re: 更好地仿真VC++关键字__uuidof  回复  更多评论   

2008-07-06 12:17 by cexer
# re: 更好地仿真VC++关键字__uuidof 回复 更多评论 删除评论
2008-07-06 02:15 by 放屁啊狗
我感觉ms的com快走向末路了,没有啥创新。ms走的就是自我封闭,自恋、自残的路线


Microsoft的技术从刚诞生的时候,会被人认定要不幸夭亡。当它成长成熟起来的时候,又会被认定在新技术四面夹击的情况下必定被淘汰。但是事实证明了,那些担忧都是多余的嘛,现在微软的COM还是软件组件模型的最广泛实现和应用的方式。我相反觉得,微软走的路线并不是封闭自恋,而是学习各家所长并融汇到自己的技术里。

# re: 更好地仿真VC++关键字__uuidof  回复  更多评论   

2008-07-06 12:23 by cexer
谢谢上面回复的www.helpsoff.com.cn,我这个就是一点小技巧,还真说不上是“技术”。谢谢你的支持,我会努力的。

谢谢pang,谢谢支持。

# re: 更好地仿真VC++关键字__uuidof  回复  更多评论   

2008-07-06 15:45 by www.helpsoff.com.cn
回空明流转,因为经常在cppblog上看到聊面试的,又有进而聊面试过程的,然后又进而有聊自己如何管理别人的...所以一看到这篇有思考过程有代码的文章,禁不住说“真正的”,哈哈,见谅见谅...

只有注册用户登录后才能发表评论。
【推荐】超50万行VC++源码: 大型组态工控、电力仿真CAD与GIS源码库
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理