大多数的编程语言都可以获取真实的函数地址,在汇编中,这个根本就不是问题,是正当的编程手段之一,windows也经常会应用这个称为回调

函数的东西,但VB编程受限制,只能获取标准模块中的函数地址,而且该函数地址不可在运行时获取属于静态连接

在进行对象编程时,经常用到类模块,最简单的类模块应用就是包装代码了,但遇到类似处理子类化窗口函数时经常会让你觉得很累,无法获取

类模块中指定的函数地址,于是... 你不得不绕到模块中,通过动态调用的方式实现回调函数,比起 SetWindowLong xxx,xxx,any proc address

简直太费脑筋了,而且很多新手还不能理解这种编程思路.也无法应用, 有些汇编高手开始从对象的底层做起一步一步的探索找到了 Thunk 的

解决方法,其实这个方法是MS首先做出来的,只不过被coders们加强了

利用所学的有限的知识我也做一下,争取解决他吧:


Private Function GetClassProcAddress(ByVal SinceCount As Long) As Long
'***************************************************************************************************
' VB6 历史上最简单的获取类中指定函数地址的函数诞生了,can be get address of property to value ,too
'***************************************************************************************************
Dim i As Long, jmpAddress As Long
CopyMemory i, ByVal ObjPtr(Me), 4 ' get vtable
CopyMemory i, ByVal i + (SinceCount - 1) * 4 + &H1C, 4 ' 查表
CopyMemory jmpAddress, ByVal i + 1, 4 ' 获取的函数地址实际还是一个表,是一个跳转表
GetClassProcAddress = i + jmpAddress + 5 ' 计算跳转相对偏移取实际地址
End Function


调用方法:

类模块中指定的函数地址 = GetClassProcAddress( 第几个函数 )

oo" 代码很少... 他能行吗? 没问题... 找到指定的函数地址是没问题的...

解释下这个函数,

参数 SinceCount , 是从某个类模块中最顶端的函数或属性算起,他是第几个函数

这个参数有讲究...
1. 当被查找的函数为 公用函数时,它的值就是自顶端算起的第几个函数,比如你在类模块中最顶端写的一个公用函数 WndProc,那么就传 1
如果是第2个公用函数或属性那么就传 2 依次... 注意,计算的时候要算上公用属性,公用属性也要算上,当他是函数,算做一个

2. 当被查找的函数为 局部函数时,也就是说如果是 Private 修饰的函数,则此参数值为 所有公用函数个数 + 这是第 N 个私有函数
也是从顶端算起,同样包括属性

说下原理,
对象是什么? 对象实际就是一个结构,VB,甚至 C++ 都不一定能让你真正深刻的理解最底层的对象构造,如果说 VB 能让你懂得什么叫继承

则 C++ 能让你知道对象还可以变异....对象原来是那么简单实现了那么高级的技术

再向底层看,用汇编构造对象,你就可以看到,对象原来就是一个结构,结构中包括所有公用函数,属性的地址指针,和连接,销毁函数指针等

那么,在返回到 VB,ObjPtr 可以得到对象的 vTable 指针,通过查询 vTable 就可以得到我们想要的函数指针,前提是我们要知道编译器是

按照什么样的顺序放置属性函数指针的,现在经过查询资料和测试,已经知道了,那就是 基址 + &H1C 所谓的基址其实就是vTable, &H1C就

是VB给结构添加的和必要的函数指针所占用的空间, 从vTable+&H1C 开始存储我们的函数地址,存储顺序如何,可以参照上面对 GetClassProcAddress

的参数 SinceCount 的解释.VB 把所有模块都单独的建立了一个表,每个表中又有单独的表表示他所包含的函数地址.

好了,函数和原理解释已经差不多了,再说说应用

很不幸的我要说,直接应用价值基本 = 0 , 郁闷啊... 为什么呢? 因为... 对象的函数他的第1个参数是vTable指针,第2个(暂时忘了,想起来再补)

于是你构造的函数有4个参数,但编译后该函数将有6个参数,那如果直接交给别人用,比如 APi 那还不出事吗...

会出事,但又不是不能弥补,加上少量的内嵌汇编代码,从新构造一个小函数,就可以完美的运行了,o... 还是很不错的选择

说了很多, 我也累了,就先打住了,总结起来,就是成功的用最简单的代码获取了类模块中指定的函数地址,从这个角度来说此文应该还是一精华文章吧?

等我有时间了,我会将弥补的汇编函数和 GetClassProcAddress 相结合,构造一个最简单化的代码,实现真正的类模块回调函数

 
目前有0条回应
Comment
Trackback
你目前的身份是游客,请输入昵称和电邮!