Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2003.08.21;
Скачать: [xml.tar.bz2];

Вниз

DllEntryPoint   Найти похожие ветки 

 
Толик   (2003-08-07 12:49) [0]

Уважаемые мастера. Вопрос на первый взгляд покажется простым, но меня он вгоняет в тупик. Как реализовать DllEntryPoint на Delphi? На C++ всё было просто и понятно:

#include <vcl.h>
#include <windows.h>
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
{
switch(reason){
case DLL_PROCESS_ATTACH: ShowMessage("load"); break;
case DLL_THREAD_ATTACH: ShowMessage("new thread"); break;
case DLL_THREAD_DETACH: ShowMessage("delete thread"); break;
case DLL_PROCESS_DETACH: ShowMessage("unload"); break;
default: ShowMessage("undefine value");
};
return 1;
}

при вызове LoadLibrary видим "load", при вызове FreeLibrary - "unload". В Делфях, видимо ради облегчения жизни программистов :)), ничего подобного нет, но есть некая глобальная переменная DllProc, с которой надо работать примерно так:

library MyDll;

procedure DllEntryPoint(Code: longint);
begin
case Code of
DLL_PROCESS_ATTACH: ShowMessage("load");
DLL_THREAD_ATTACH: ShowMessage("new thread");
DLL_THREAD_DETACH: ShowMessage("delete thread");
DLL_PROCESS_DETACH: ShowMessage("free");
( "undefine value")
Уважаемые мастера. Вопрос на первый взгляд покажется простым, но меня он вгоняет в тупик. Как реализовать DllEntryPoint на Delphi? На C++ всё было просто и понятно:

#include <vcl.h>
#include <windows.h>
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
{
switch(reason){
case DLL_PROCESS_ATTACH: ShowMessage("load"); break;
case DLL_THREAD_ATTACH: ShowMessage("new thread"); break;
case DLL_THREAD_DETACH: ShowMessage("delete thread"); break;
case DLL_PROCESS_DETACH: ShowMessage("unload"); break;
default: ShowMessage("undefine value");
};
return 1;
}

при вызове LoadLibrary видим "load", при вызове FreeLibrary - "unload". В Делфях, видимо ради облегчения жизни программистов :)), ничего подобного нет, но есть некая глобальная переменная DllProc, с которой надо работать примерно так:

library MyDll;

procedure DllEntryPoint(Code: longint);
begin
case Code of
DLL_PROCESS_ATTACH: ShowMessage("load");
DLL_THREAD_ATTACH: ShowMessage("new thread");
DLL_THREAD_DETACH: ShowMessage("delete thread");
DLL_PROCESS_DETACH: ShowMessage("free");
else ShowMessage("undefine value");
end;
end;

begin
DllProc := @DllEntryPoint;
DllEntryPoint(DLL_PROCESS_ATTACH);
end.

При вызове LoadLibrary действительно появляется "load" - оно и понятно: в коде инициализации происходят явный вызов DllEntryPoint. Вот только при вызове FreeLibrary ничего не происходит. Так как же правильно работать в Делфях c DllEntryPoint?


 
Tiny   (2003-08-07 12:58) [1]

вот сейчас делаю то же самое в своем проекте - и все работает....
DllEntryPoint(DLL_PROCESS_ATTACH) - а это нахрена тут???


 
Толик   (2003-08-07 13:13) [2]

>>DllEntryPoint(DLL_PROCESS_ATTACH) - а это нахрена тут???
дело в том, что в своей процедуре DllEntryPoint я хочу управлять некими глобальными объектами. Во время вызова ф-и _InitDll значение переменной DllProc = 0. Ну и понятно, что сама по себе она не вызовется. Вот и приходится её вызывать явно в коде инициализации библиотеки. Честно говоря была надежда на то, что при выгрузке библиотеки из памяти где-то в районе вызова ф-и ExitDll вызовется и моя процедура DllEntryPoint с параметром DLL_PROCESS_DETACH, но этого не происходит. В чём же дело?


 
Skier   (2003-08-07 14:25) [3]

>Толик © (07.08.03 13:13)
А ты не забыл что глобальные переменные обнуляются при каждой
загрузке библиотеки ?


 
Толик   (2003-08-07 14:45) [4]

to Skier © (07.08.03 14:25)
Так ведь переприсваивание значения DllProc происходит каждый раз при инициализации библиотеки. Более того, похоже, что дело не в этом. Вот что говорит Borland по этому поводу: http://community.borland.com/article/0,1410,27753,00.html - перекомпиляция System.pas, не больше не меньше. Спрашивается, почему сразу нельзя было реализовать DllEntryPoint так, как это рекомендует делать Microsoft. А то начинают придумывать всякие извращения, а потом с ними бороться...


 
Skier   (2003-08-07 14:59) [5]

>Толик © (07.08.03 14:45)

> Так ведь переприсваивание значения DllProc происходит каждый
> раз при инициализации библиотеки.

Секция инициализации и финализации выполняется один раз.
Неужели имеет место "плюха" от Borland-а ?


 
Толик   (2003-08-07 15:08) [6]

Судя по тому, что сказано в ответе

Due to RTL changes, the DLLProc was not being called appropriately. This change will fix the change that you may have noticed. Once you have completed the change, you will need to recompile the RTL and copy the new System.dcu into your project directory. Your project will use the newly created System.dcu with the fix included. In System.pas, navigate down to this method @@skipTLSproc


@@skipTLSproc:
{ Call any DllProc }
PUSH ECX
MOV ECX,[ESP+8]//Changed from 4 to 8.
TEST ECX,ECX
JE @@noDllProc
MOV EAX,[EBP+12]
MOV EDX,[EBP+16]
CALL ECX

то похоже, что плюха та ещё.


 
Skier   (2003-08-07 15:12) [7]

Жуть ! :)


 
Tiny   (2003-08-07 15:17) [8]

Мдя... в D7 вроде все сразу работает.Тьфу-тьфу-тьфу...))


 
Толик   (2003-08-07 15:27) [9]

to Tiny (07.08.03 15:17)
А нельзя ли мне на почту скинуть System.dcu и System.pas из 7 Делфи?


 
Толик   (2003-08-07 17:40) [10]

у неужели и правда всё так запущено?


 
icWasya   (2003-08-07 18:22) [11]

где-то этот вопрос уже поднимался
смысл был в том, что ShowMessage в FreeLibrary НЕ РАБОТАЕТ

попробуй поставить точку останова на строке
DLL_PROCESS_DETACH:

и проверь - попадаешь ли ты туда или нет


 
Юрий Зотов   (2003-08-07 21:04) [12]

> Толик

> Спрашивается, почему сразу нельзя было реализовать
> DllEntryPoint так, как это рекомендует делать Microsoft.
> А то начинают придумывать всякие извращения, а потом с ними
> бороться...

IMHO, катить баллоны на Borland незачем. Конечно, не Вы первый, но неужели Вы полагаете, что загрузка и выгрузка DLL в Delphi не была протестирована самым тщательным образом? Можете даже и не сомневаться - уж что-что, а ЭТО было проверено и отлажено как следует. Да и за все время существования Delphi Вы далеко не первый DllProc юзаете - а уж ТАКАЯ ошибка, если бы она была, то всплыла бы давным-давно и давным-давно была бы исправлена.

Короче - вот этот код у меня вполне нормально работает (Delphi 5).

library Project1;

uses
Windows;

procedure DllEntryPoint(dwReason: DWORD);

procedure ShowMessage(Text: string);
begin
MessageBox(0, PChar(Text), "DLL entry point", MB_OK or MB_ICONINFORMATION or MB_TASKMODAL)
end;

begin
case dwReason of
DLL_PROCESS_ATTACH: ShowMessage("DLL_PROCESS_ATTACH");
DLL_THREAD_ATTACH: ShowMessage("DLL_THREAD_ATTACH");
DLL_THREAD_DETACH: ShowMessage("DLL_THREAD_DETACH");
DLL_PROCESS_DETACH: ShowMessage("DLL_PROCESS_DETACH")
else ShowMessage("undefined reason")
end
end;

begin
if DllProc = nil then DllProc := @DllEntryPoint;
DllEntryPoint(DLL_PROCESS_ATTACH)
end.

==========================================

type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
private
FDLL: THandle;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
FDLL := LoadLibrary("Project1.dll")
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
FreeLibrary(FDLL)
end;


 
Ученик   (2003-08-07 21:07) [13]

Можно еще OutputDebugString использовать


 
icWasya   (2003-08-08 09:59) [14]

а если не нужны DLL_THREAD_ATTACH и DLL_THREAD_DETACH то можно обойтись секциями initialization / Finalization в unit`ах


 
Толик   (2003-08-08 11:24) [15]

to Юрий Зотов © (07.08.03 21:04)
Увы, но Ваш код, скопированный один в один, под D6 не работает. Я не упрекаю Borland понапрасну, я констатирую факт - на http://community.borland.com/ есть упоминание об этой ошибке и в качестве рекомендации по её исправлению Borland рекомендует ни больше ни меньше, как you will need to recompile the RTL and copy the new System.dcu into your project directory, т.е. перекомпилировать System.pas. Так что похоже, что …загрузка и выгрузка DLL в Delphi не была протестирована самым тщательным образом….

P.S.
initialization и finalization отрабатывают корректно, так что можно просто обойти эту проблему, но у меня вызвало недоумение подобное поведение DllProc, почему я и задал этот вопрос, ведь раньше я никогда ни с чем подобным не сталкивался. Похоже, что эта проблема появилась в D6 и судя по Tiny (07.08.03 15:17) была исправлена в D7.



Страницы: 1 вся ветка

Форум: "Основная";
Текущий архив: 2003.08.21;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.49 MB
Время: 0.009 c
14-68445
TButton
2003-07-08 18:47
2003.08.21
beta Тестирование


1-68362
Evgeny
2003-08-07 10:04
2003.08.21
Stream


1-68389
Olegka
2003-08-07 17:30
2003.08.21
Диалог сохранения в папку


1-68338
mOOx_
2003-08-08 15:43
2003.08.21
С чем едят Assign...


3-68224
М. Дмитрий
2003-07-27 20:01
2003.08.21
Имена таблиц в MSAccess?





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский