揭开native event的面纱

原创 2004年07月09日 08:52:00

 

这是我的第3篇关与native event的随笔。第一篇对native event作了简介。第二篇报告一个BUG(MSVC TEAM说这是一个以知的BUG,可是在VC8Express里仍然存在)。这一篇我们看看native event是如何实现的,并且尝试解决我们遇到的BUG。

从VC7(Microsoft Visual C++ .NET (2002) )开始MSVC提供了native event这一机制,试图为C++引入一个实现delegate的办法。一共提供了4个扩展关键子:__event (定义一个event),__raise(触发一个event),__hook(将一个成员函数连到event上),__unhook(去掉指定的函数),和两个作用在类上的特性:event_source(一个事件源),event_receiver(一个事件接受者)。

为什么会提供这么多看上去很丑陋的关键子呢?这些关键子生成了什么样的代码呢?

可以使用下面的编译命令来编译我在第二篇随笔里的代码。

cl /Fx /Fas native_event.cpp

/Fx编译选项会生成一个native_event.mrg.cpp,这是MSVC编译器对特性作了展开以后生成的源代码。/Fas编译选项生成相应的汇编代码。

我们看看native_event.mrg.cpp就足够了解native event的实现方法了。

__event关键子被展开成为一个事件函数链表指针,一个虚构造体,一个模板构造体,3个模板函数,一个名为__RemoveAllEventHandlers的成员函数,一个与event名同名的inline函数。除此以外还有4个辅助结构体。 可见event机制是非常类似宏定义的实现方案

__hook通过__AddEventHandler模板函数将函数指针追加到函数链表里。__unhook从链表中删除函数指针。

__raise本身没有什么用处。实际调用的事件函数的时候,会循环调用函数链表里的函数。函数链表的每个节点里都存储了对象实体指针(this)和成员函数指针。成员函数指针同void*指针的转换利用了__eventingGetAddr这个灵巧的辅助类。

虽然代码看上去有点乱,但并不是很长,应该很容易看懂。

我在第二篇随笔里提到的bug,发生在

        int __isEqual(void* p, void* pfn)
        {
            return ((T*) p == this->p) && (__eventingGetAddr<T>::__getMAddr(pfn) == (void ( T::*) ()) pmfn);
        }
这个函数里。多继承的情况下对(void ( T::*) ()) 形式的指针做比较是比较微妙的,明明相等的指针确返回了false。查看汇编代码发现一共比较了8个byte,两个DWORD PTR,具体为什么这么做我还需要做一些分析。

看上去一个可行的代替方案是:

        int __isEqual(void* p, void* pfn)
        {
            return ((T*) p == this->p) && pfn == __eventingGetAddr<T>::__getVAddr((void (T::*) ()) pmfn));
        }
将函数指针转换成void*,然后再做比较。从asm看到这产生了高效的代码。

这个BUG导致的后果就是:无法在ATL/WTL中使用native event。这使的这一机制几乎失去了意义。

警告:使用native event要小心。

建议:在MSVC改正BUG之前不要使用native event。

CodeProject里有一篇最近发表的文章提出一种FastDelegate方法,似乎是不错的single-target delegate 解决方案。boost的function和signals则是更加值得关注的。

零基础汇编揭开CPU的神秘面纱(堆栈、CPU保护模式)

汇编语言是所有编程语言中难度最大最不容易理解的一种编程语言,每个同学对它都是敬而远之。但是它对真正掌握计算核心原理、理解操作系统真正奥妙有着不可替代的作用。    本视频讲师应用深入浅出的语言来...
  • maochengtao
  • maochengtao
  • 2014年09月21日 21:50
  • 1335

揭开Wayland的面纱

(一)    揭开Wayland的面纱(一):X Window的前生今世 古老的X Window和现代的桌面技术 X Window在1984年由MIT研发,它的设计哲学之一是:提供机制...
  • yazhouren
  • yazhouren
  • 2013年12月04日 15:37
  • 1092

揭开MSXML4.0的面纱

揭开MSXML4.0的面纱时间:2001/05/09 11:09作者:孙一中 中国XML联盟  2001年4月16日,微软发布了MSXML 解析器4.0的技术预览版本。比起3.0版本,有不少改进的地方...
  • x86
  • x86
  • 2001年05月16日 13:10
  • 3973

揭开TXT炸弹的神秘面纱

  • 2013年12月01日 13:39
  • 143KB
  • 下载

揭开j2ee的神秘面纱

  • 2013年04月03日 15:31
  • 719KB
  • 下载

你未必知道的CSS故事:揭开leading的面纱.doc

  • 2013年01月23日 16:51
  • 303KB
  • 下载

揭开J2EE集群的神秘面纱

  • 2013年03月07日 16:26
  • 870KB
  • 下载

一步一步揭开Android应用程序的神秘面纱

  • 2012年01月13日 09:56
  • 89KB
  • 下载

揭开正则表达式的神秘面纱

  • 2010年03月15日 13:50
  • 145KB
  • 下载

用Delphi揭开外挂的神秘面纱

  • 2011年01月27日 18:45
  • 45KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:揭开native event的面纱
举报原因:
原因补充:

(最多只允许输入30个字)