【发布时间】:2021-03-29 21:10:24
【问题描述】:
快速提问 - 我刚刚通过使用低级复制内存 API 更改其 VTable 中的条目来测试类的覆盖方法。
背景
我已经取得了一些成功,如果它们具有相同的签名,则可以交换一个类的 VTable 中的 2 个条目。所以像这样的类定义:
Option Explicit
Public Sub Meow()
Debug.Print "Meow"
End Sub
Public Sub Woof()
Debug.Print "Woof"
End Sub
... 生成一个像这样的 VTable:
...我可以交换位置 7 和 8 的条目以使 cls.Meow 打印 Woof ,反之亦然。我还可以将一个类的 VTable 中的条目与完全不同的 VTable 交换(前提是我不尝试通过调用 Me.anything 来取消引用隐式 this 指针)
这样我就可以再上课了
Option Explicit
Public Sub Tweet()
Debug.Print "Tweet"
End Sub
并将Woof 的行为从一个与另一个Tweet 交换。不太复杂,有需要的可以分享代码。
我不能做什么...
...但是,想知道如何用标准模块中的方法交换类方法吗?
根据this 文章,看来构建 VBA 的 COM 机制需要 VBA 隐藏的两个类方法:
- 他们有一个隐含的
this指针 - 他们返回 HRESULT (
typedef long)
原来如此
Public Sub Meow()
在一个类模块中Class1等价于
Public Function Meow(ByVal this As LongPtr) As Long
我也试过
Public Function Meow(ByRef meObj As Class1) As Long
Public Function Meow(ByRef meObj As Class1) As LongPtr 'but HResult is 32 bit int
Public Sub Meow(ByVal this As LongPtr)
等等。但是当我尝试从 VTable 调用该方法时,VBA 总是崩溃。所以我有点茫然。我想知道 64 位计算机上的情况是否有所不同,或者标准模块函数是否对调用堆栈做了一些奇怪的事情。问题是我见过examples of code,其中整个 VTable 是由标准模块函数组装而成的,所以我知道这是可能的,但只是不确定如何正确转换签名
如何使用标准模块中定义的方法覆盖 VTable 条目?
【问题讨论】:
-
在 x64 上的行为完全相同。但是,您可以将 IUnknown 和 IDispatch 方法“重定向”到 .bas 模块中的函数(以及链接示例中的 IEnumVariant 方法)。我认为这些工作是因为它们不是 VB。我认为由于 VB 类的工作方式,您无法重定向 VB 类方法。考虑
Me关键字(其行为类似于函数/属性获取)。您不可能在 .bas 模块中复制Me行为。幕后一定有更多的事情发生。也许调用约定也不同。
标签: vba com 64-bit vtable iunknown