Метод COM смещает в Delphi

В Delphi, как я узнаю адрес метода COM? Я могу hardcode смещения

//0 is the offset of the QueryInterface method
p := TPonterArray(pointer(SomeInterface)^)[0];

но я предпочел бы использовать символьные имена. Следующее, очевидно, не работает:

var M : TMethod;
...
M := TMethod(SomeInterface.QueryInterface);

Спасибо!

9
задан Dmitry Streblechenko 1 July 2010 в 06:11
поделиться

3 ответа

Вы можете использовать директиву ассемблера vmtoffset для получения байтового смещения метода интерфейса относительно начала таблицы методов интерфейса. Посмотрите, например, на реализацию _IntfCast в System.pas:

call dword ptr [eax] + vmtoffset IInterface.QueryInterface
...
call dword ptr [eax] + vmtoffset IInterface._Release

Первое выражение добавляет 0, второе - 8.

Однако вы не можете параметризовать эти выражения. Это константы времени компиляции, поэтому вы не можете выбрать, какой метод вам нужен во время выполнения. Вам нужно заранее представить все возможные имена методов.

Все, что вам действительно нужно, это QueryInterface. Получив его, вы можете вернуть любой прокси-объект, который вы хотите, который может перехватывать вызовы всех остальных методов.

6
ответ дан 2 November 2019 в 23:58
поделиться

Ваш код неверен, поскольку ссылка на интерфейс - это не указатель на таблицу методов интерфейса, а указатель на указатель на таблицу методов интерфейса. Именно так интерфейсы Delphi реализованы на двоичном уровне. Трудно сказать больше и указать на ошибку в вашем коде, так как вы не привели пример кода, который можно скомпилировать. Используйте следующий код для правильного преобразования интерфейсной ссылки в указатель метода, идея взята из демонстрации Барри Келли о создании указателя метода из ссылки на метод:

procedure IntRefToMethPtr(const IntRef; var MethPtr; MethNo: Integer);
type
  TVtable = array[0..999] of Pointer;
  PVtable = ^TVtable;
  PPVtable = ^PVtable;
begin
  // QI=0, AddRef=1, Release=2, etc
  TMethod(MethPtr).Code := PPVtable(IntRef)^^[MethNo];
  TMethod(MethPtr).Data := Pointer(IntRef);
end;

Если вы предпочитаете символьные имена для MethNo, то лучше объявить их самостоятельно как константы смещения

.
2
ответ дан 2 November 2019 в 23:58
поделиться

Я не думаю, что Delphi поддерживает это. Жесткое кодирование смещений, вероятно, единственное, что будет работать, поскольку компилятор не считает методы интерфейса символами, значение которых может быть присвоено указателю функции, как это могут быть назначены объектные методы или автономные функции.

Почему вы пытаетесь это сделать, кстати?

3
ответ дан 2 November 2019 в 23:58
поделиться
Другие вопросы по тегам:

Похожие вопросы: