Вопрос, поднятый пользователем, касается работы с переменным количеством аргументов в методах COM-интерфейсов, которые используют калл-конвенцию __stdcall. В частности, рассматривается интерфейс ICallFrame и его метод Invoke, который принимает переменное количество аргументов. В документации указано, что директива varargs в Delphi работает только с внешними функциями и только с калл-конвенцией cdecl. Однако, Invoke объявлен с калл-конвенцией __stdcall, которая предполагает, что каллер (вызывающая сторона) не очищает стек после вызова функции. В связи с этим возникает вопрос о том, как обработать метод Invoke в Delphi.
Решение проблемы
Пользователь нашел решение, предложенное Rudy, которое заключается в определении типа функции с калл-конвенцией cdecl и использованием директивы varargs. В примере кода тип TfnInvoke определяется как функция с калл-конвенцией cdecl и переменным количеством аргументов. Затем, с помощью функции GetInterfaceMethod, получается указатель на метод интерфейса, который можно вызвать с использованием определенного типа TfnInvoke.
Пример кода
type
TfnInvoke = function(this: Pointer; pvReceiver: Pointer): HRESULT; cdecl varargs;
implementation
function GetInterfaceMethod(const Intf: Pointer; methodIndex: dword): Pointer;
begin
Result := Pointer(pointer(dword_ptr(Pointer(Intf)^) + methodIndex * SizeOf(Pointer))^);
end;
...
var
Invoker: TfnInvoke;
...
// Не забудьте методы IUnknown при подсчете!
Invoker := GetInterfaceMethod(myIntf, 21);
Invoker(myIntf, FObject, 11, 17.3);
Важные замечания
Директива varargs в Delphi используется только для внешних функций с калл-конвенцией cdecl.
Калл-конвенция __stdcall не поддерживает переменное количество аргументов, так как каллер не очищает стек после вызова функции.
Delphi не может генерировать функции с переменным количеством аргументов и калл-конвенцией __stdcall, но может использовать внешние C-функции, объявленные с использованием varargs.
При объявлении функции в Delphi с использованием varargs необходимо указать калл-конвенцию cdecl.
Альтернативный ответ
В качестве альтернативного подхода рассматривается возможность определения глобальной функции с калл-конвенцией cdecl и varargs, которая затем используется для вызова методов интерфейса путем приведения типа.
Подтвержденный ответ
По информации, полученной от Remy Lebeau, компилятор Visual Studio при обнаружении переменного количества аргументов в функции с калл-конвенцией __stdcall автоматически меняет калл-конвенцию на cdecl. Это означает, что функция будет использовать калл-конвенцию cdecl даже если она объявлена с калл-конвенцией __stdcall.
Заключение
Работа с переменным количеством аргументов в Delphi для COM-объектов требует понимания особенностей калл-конвенций и возможности их автоматической переподгонки компилятором. При правильном подходе можно успешно интегрировать COM-интерфейсы, использующие переменное количество аргументов, в свои Delphi-проекты.
Вопрос касается работы с методами COM-интерфейсов, принимающими переменное количество аргументов, и их реализации в Delphi с учетом калл-конвенции `__stdcall`, а также возможностей директивы `varargs` в Delphi и особенностей компилятора Visual Studio.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.