Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Как передать в dll адрес процедуры?..


Страницы:   1 2

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]

что, ни разу свойству-событию не присваивал адрес обработчика?


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо