![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Как передать в dll адрес процедуры?..
Franzy © (2009-08-31 13:39:00)Обсуждение было закрыто, хотя еще не все понятно. Процитирую:
Franzy (31.08.09 13:04)
У меня программная библиотека (dll) делает расчеты, порой весьма времяемкое. Теперь хочу сделать так, чтобы библиотека могла как-нибудь сообщать прогресс выполнения (например, в процентах). Т.е. нужен некий механизм "вещания в эфир" (поскольку библиотека не знает, кто ее будет вызывать). Для этого можно использовать мессаджи виндоуз или что-то еще?
stas © (31.08.09 13:17) [1]
можно передавать адрес процедуры, которая будет вызываться в момент продвижения прогресса допустим на 1%, либо в нее будет засыалаться параметр % прогресса.
<Цитата>
stas © (31.08.09 13:18) [2]
т.е. твоя функция должна принимать адрес процедуры и вызывать ее в нужном месте.
----------------------------
Так как передавать в dll адрес процедуры? Dll и основная программа написаны на разных языках.
Медвежонок Пятачок (2009-09-01 13:50:00) [1]молодец. стройная, грациозная конструкция из кучи подпорок
Franzy (2009-09-01 13:46:00) [2]Ну, я просто ввел глоб. переменные DoReport: boolean и Rep : TCallbackReport. Плюс объявил процедуру
procedure SitRep(s: string)
if DoReport then rep(s);
End;
А в альтернативной интерфейсной функции написал
rep := CallBackReport;
DoReport:=true;
Ну и добавил в нужных местах вызовы SitRep в самой расчетной процедуре. Все работает при любых вызовах, и старом, и новом.
Сергей М. (2009-09-01 13:19:00) [3]
> коллбек в них будет недоступен
Не то что недоступен - они вообще знать не знают ни о каких колбэках, ибо писались он тобой до того как тебе пришло в голову организовать дополнительную колбэк-функциональность.
Franzy (2009-09-01 13:17:00) [4]Можно :) Нужно только глобальную переменную соотв. типа объявить. Вопрос снят.
Franzy (2009-09-01 13:14:00) [5]Кстати, а можно как-то глобальный алиас процедуры создать? А то у меня в длл интерфейсная функция - это всего лишь обертка и все расчетные процедуры вызываются уже из нее. Соответственно, насколько я понимаю, коллбек в них будет недоступен. Это обстоятельство можно как-то забороть?
Сергей М. (2009-08-31 17:01:00) [6]
> расширить интерфейс, добавив в него альтернативный вызов
> расчетной процедуры (с коллбеком). Таким образом сохраняется
> и обратная совместимость, и появляются новые возможности
Вполне логичное решение.
Franzy (2009-08-31 16:59:00) [7]Вы не поняли. Есть длл, которая проводит некий расчет. Алгоритм расчета постоянно улучшается, но при этом интерфейс общения длл с программой остается прежним. Программ, использующих эту длл, на текущий момент уже несколько, причем написаны они на разных языках. Обновлять их все при изменении интерфейса будет проблематично.
Я хочу улучшить длл так, чтобы она могла отчитываться о прогрессе расчета. Пока что придумал такой способ: расширить интерфейс, добавив в него альтернативный вызов расчетной процедуры (с коллбеком). Таким образом сохраняется и обратная совместимость, и появляются новые возможности.
Всем спасибо (особенно Юрию Зотову), проблема, кажется, решена.
Юрий Зотов (2009-08-31 16:31:00) [8]> Franzy (31.08.09 16:14) [12]
> использование колбека подразумевает изменение кода и dll, и всех exe (и
> новой, и старых, тоже использующих эту dll), что мне не очень подходит.
> Хотелось бы сохранить полную обратную совместимость.
Потребовалась НОВАЯфункциональность - оповещение о позиции прогрессбара. Спрашивается - каким волшебным способом можно реализовать эту НОВУЮ функциональность, НЕ МЕНЯЯ кода Exe и DLL?
Любой способ все равно потребует изменения кода. Чудес не бывает.
Сергей М. (2009-08-31 16:27:00) [9]
> модное - пайп!
Сейчас моднее через блютуз почтой обмениваться)
Медвежонок Пятачок (2009-08-31 16:26:00) [10]Ну как как?
Сказано же модное - пайп!
:)
Сергей М. (2009-08-31 16:23:00) [11]
> сохранить полную обратную совместимость
Каким образом модификация Dll, подразумевающая новую, доселе нефигурировавшую процедуру и никак не затрагивающая доселе фигурировавшие, может повлиять на обратную совместимость ?
Медвежонок Пятачок (2009-08-31 16:20:00) [12]А вообще угораю я над кадрами.
Приходит спрашивающий, задает вопрос.
ПРиходит мастер, все разжевывает и кладет в клювик (поцеловать только забыл)
На что спрашивающий отвечает: все это конечно хорошо, но мне это не подходит.
Медвежонок Пятачок (2009-08-31 16:17:00) [13]менять код придется везде в любом случае при любом избранном способе "вещания"
Franzy (2009-08-31 16:14:00) [14]Спасибо за обстоятельный ответ.
Тем не менее, насколько я понял, использование колбека подразумевает изменение кода и dll, и всех exe (и новой, и старых, тоже использующих эту dll), что мне не очень подходит. Хотелось бы сохранить полную обратную совместимость.
Юрий Зотов (2009-08-31 16:08:00) [15]> Franzy (31.08.09 13:39)
Этот прием назвается "обратный вызов" (callback). При вызове функции мы передаем ей адрес другой функции и первая, когда ей надо, сама вызывает вторую. Такой механизм часто используется, например, функциями WinAPI. Заметьте, что эти функции написаны на C, но, тем не менее, запросто вызываются програмой Delphi и сами запросто вызывают дельфишный же callback - так что нет разницы, на каких языках все эти функции написаны, важно лишь, чтобы было соблюдены соглашения о вызове (см. в справке тему "Calling conventions").
1. Сначала определяем прототип callback-функции, например:
type
TMyCallbackProc = procedure(ProgressPosition: integer); stdcall;
Этот прототип должен быть известен и в EXE (для того, чтобы там эту функцию правильно написать), и в DLL (для того, чтобы ее оттуда правильно вызвать).
2. Функция DLL может иметь сколько угодно любых параметров, но среди них обязан быть один параметр типа TMyCallbackProc, например:
procedure MyDLLProc(..., Callback: TMyCallbackProc); stdcall;
3. Внутри функции MyDLLProc можно в любой момент вызвать callback-функцию в соответствии с ее прототипом, например:
CallBack(85);
4. Реализуем callback-функцию в EXE, например:
procedure MyCallbackProc(ProgressPosition: integer); stdcall;
begin
... // Обновляем ProgressBar
end;
5. Теперь все готово - вызываем из Exe функцию DLL, передавая ей адрес callback-функции:
MyDLLProc(..., @MyCallbackProc);
Сергей М. (2009-08-31 16:07:00) [16]
> если такой процедуры нет в головной программе, будет вылет
Зачем же подсовывать фуфло вместо реального адреса реально существующей процедуры ?
> Склоняюсь к мысли организовать пайп
Ядреной бомбой по воробьям ?)
Медвежонок Пятачок (2009-08-31 16:06:00) [17]Ведь если такой процедуры нет в головной программе
Как же было страшно писателю TButton'а, когда он думал, а вдруг программист на ОнКлик никакого обработчика не повесит.
stas (2009-08-31 16:04:00) [18]Franzy (31.08.09 15:59) [7]
можно Nil передавать вмето адреса, а в dll его обрабатывать.
Franzy (2009-08-31 15:59:00) [19]Тут есть один минус в плане обратной совместимости. Ведь если такой процедуры нет в головной программе, будет вылет... Склоняюсь к мысли организовать пайп.
Медвежонок Пятачок (2009-08-31 15:58:00) [20]что, ни разу свойству-событию не присваивал адрес обработчика?