Сигнатуры функций, экспонируемых FARом плагинам

Вам не хватает чего-то в Far? Вы считаете, что вашу идею стоит услышать? Пишите сюда.
Post Reply
awson
Posts: 61
Joined: Fri 11 Sep, 2009 13:22
Has thanked: 1 time
Been thanked: 1 time

Сигнатуры функций, экспонируемых FARом плагинам

Post by awson »

Если тема обсуждалась, сильно, пжлст, не пинайте. Я сходу не нашел.

Итак. Все мне известные - *кроме* FARа - системы экспортируют свои интерфейсы по схеме типа vtbl. Типичный пример - Microsoft COM. Т. е. интерфейс - это таблица указателей на функции, каждая из которых первым (возможно, скрытым) параметром имеет указатель на саму эту таблицу.

У функций FARа такого первого параметра нет. Казалось бы, все правильно, он же все равно не используется, но почему же Microsoft (и все остальные) его оставляют? Только ли для того, чтобы быть бинарно совместимыми с C++-ными объектами? Оказывается, такая схема дает еще одно важное преимущество. Если я захочу превратить указатель на функцию из интерфейса FARa в обычную C-функцию, у меня получится, например так:

Code: Select all

void WINAPI FarRecursiveSearchReified(FARSTANDARDFUNCTIONS *this, const wchar_t *InitDir, const wchar_t *Mask, FRSUSERFUNC Func, DWORD Flags, void *Param) {
  this->FarRecursiveSearch(InitDir, Mask, Func, Flags, Param);
}
А если б было как в COM, то получилось бы так:

Code: Select all

void WINAPI FarRecursiveSearchReified(FARSTANDARDFUNCTIONS *this, const wchar_t *InitDir, const wchar_t *Mask, FRSUSERFUNC Func, DWORD Flags, void *Param) {
  this->FarRecursiveSearch(this, InitDir, Mask, Func, Flags, Param);
}
Казалось бы, нафига козе баян? Какой-то ненужный лишний параметр? Вот тут-то и оказывается, что во втором варианте функция редуцируется к

Code: Select all

movl	4(%esp), %eax
jmp	*xxx(%eax)
где xxx - смещение FarRecursiveSearch в this. В первом же варианте будет куча кода по перепихиванию всех параметров в стеке, вызова и возврата. Это происходит потому что у FarRecursiveSearch и FarRecursiveSearchReified разные сигнатуры. Более того, во втором случае код вообще не зависит от сигнатуры конкретной функции, а зависит только от ее смещения в таблице и его можно тривиально сгенерировать.

Для людей, которые пишут плагины на C/C++ это не нужно. Но например, если писать на Хаскелле, во втором варианте делать это будет намного проще, а сам код будет работать быстрее. Думаю, это справедливо и для других языков, имеющих стандартный FFI к С.
User avatar
chupakabra
Posts: 1023
Joined: Wed 27 Jul, 2005 19:36
Contact:

Re: Сигнатуры функций, экспонируемых FARом плагинам

Post by chupakabra »

Каково предназначение обертки FarRecursiveSearchReified?
awson
Posts: 61
Joined: Fri 11 Sep, 2009 13:22
Has thanked: 1 time
Been thanked: 1 time

Re: Сигнатуры функций, экспонируемых FARом плагинам

Post by awson »

Ну, "философски" она позволяет как бы заранее создать функцию, которой пока нет. Т. е., вне контекста интерфейса (указателя на FARSTANDARDFUNCTIONS) ее нет, нет ее объектного кода, ее невозможно прилинковать к другому коду и т. д. Только получив этот интерфейс мы можем взять указатель на нее и ее использовать. С помощью этой обертки мы это проделываем заранее и получаем функцию, которая есть, даже когда интерфейса нет, для которой есть код, с ней можно линковать другой код и т. д. Конечно, вне контекста интерфейса она бессмысленна, поэтому она этот контекст получает в виде параметра.

Практически же эта обертка может облегчить работу написание плагинов на языках, имеющих FFI к функциям со стандартными calling convention (ccall, stdcall и. т. д.). Те, кто постоянно используют C/C++, забывают (поскольку синтаксис вызова одинаковый), что функция и указатель на нее - в общем случае не одно и то же. Хотя, например, Хаскелл умеет работать и с внешними функциями и с указателями на них - для конверсии для каждой функции нужно явно декларировать конвертор с полной сигнатурой (фактически при этом компилятор сгенерирует что-то типа упомянутых мной оберток). Или нужно писать те самые обертки самому. НО. В первом случае нужно руками написать обертку для каждой функции, экспонируемой FARом со всеми геморройными параметрами, а во втором - сгенерировать автоматически для всех разумных смещений. Самое смешное, что у меня они уже сгенерированы и давно работают для разных интерфейсов и библиотек - от COM до Berkeley DB.
Post Reply

Return to “Предложения и идеи”