Быстрый вопрос - я только что тестировал методы перезаписи класса, изменяя записи в его VTable, используя низкоуровневый api памяти для копирования.
Задний план
У меня был некоторый успех, и я могу поменять местами 2 записи в VTable класса, если они имеют одинаковую подпись. Итак, определение класса вроде этого:
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 совершенно другого (при условии, что я не пытаюсь разыменовать неявный указатель this
, вызывая Me.anything
)
Так что я могу сделать еще один урок
Option Explicit
Public Sub Tweet()
Debug.Print "Tweet"
End Sub
и поменять местами поведение Woof
с одного на Tweet
с другого. Не слишком сложно, могу поделиться кодом, если он понадобится людям.
Что я не могу сделать ...
... однако выяснить, как заменить метод класса методом из стандартного модуля?
На основании этой статьи, Похоже, что механизм COM, на котором построен VBA, требует двух методов класса, которые скрывает 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)
и т.д. Но VBA всегда дает сбой, когда я пытаюсь вызвать метод из VTable. Так что я немного растерялся. Интересно, все ли по-другому на 64-битном компьютере, или стандартные функции модуля делают что-то странное со стеком вызовов. Дело в том, что я видел примеры кода, где весь VTable собран из стандартных функций модуля, поэтому я знаю, что это возможно, но просто не знаю, как правильно преобразовать подписи
Как я могу перезаписать запись VTable методом, определенным в стандартном модуле?
Me
(которое ведет себя как функция / свойство get). Невозможно воспроизвести поведениеMe
в модуле .bas. За кулисами должно происходить больше событий. Может быть, соглашение о вызовах тоже другое. - person Cristian Buse   schedule 23.12.2020