PDA

View Full Version : سوال: استفاده از event توی dll برای دلفی.



milad7091
سه شنبه 10 آذر 1394, 12:19 عصر
با سلام.
دوستان من یک کامپوننت دارم و میخوام اونو تبدیل کنم به یک dll. مشکم اینه که این کامپوننت یک رویداد event داره و مشخص نیست چه موقع fire میشه.
الان میخوام یک تابع خارج از dll درست کنم و بگم هر زمانی که اون رویداد fire شد این فانکشت من اجرا بشه. نمیخوام کامپوننتم رو بدم کسی. فقط میخوام dll رو داشته باشن که بتونن ازش توی زبان های دیگه هم استفاده کنن.
توی اینترنت زیاد سرچ کردم. ولی چیزی دستگیرم نشد. ممنون میشم کمکم کنین.

Mask
سه شنبه 10 آذر 1394, 12:38 عصر
میتونید از Post مسیج برای هندل کردن ایونت استفاده کنید.

milad7091
سه شنبه 10 آذر 1394, 13:21 عصر
ممنون از پستتون. ولی من نتونستم چیزی پیدا کنم که بتونه کارمو راه بندازه. این 2 تا رویداد زیر توی کامپوننت من هستن. من نمیدونم چطور باید پیاده سازیش کنم.
توی کلاسم رویداد به اسم OnConnect هست و متغییری داره که از نوع int هست.
و یه رویداد دیگه به LinehangUp که اون 2 تا متغییره Int داره.

Mask
سه شنبه 10 آذر 1394, 19:54 عصر
اگه بتونید واضح تر و کامل تر توضیح بدید، میشه خیلی دقیقتر جواب داد.

milad7091
شنبه 14 آذر 1394, 08:05 صبح
ممنون از پاسختون.
من یک dll میخوام درست کنم که توی این dll از یک کامپوننت استفاده کنم.
توی این کامپوننت 2 تا ایونت وجود داره.
- شماره یک اینه که وقتی دستگاه USB رو متصل میکنم به کامپیوتر اجرا میشه و اسمشم اینه OnConnect
-شماره دو هم زمانی که دیوایس رو از USB خارج میکنم اجرا میشه که اسمه اون OnDisConnect هست.
حالا من میخوام که برنامه نویس بتونه از این 2 تا رویداد استفاده کنه.
خودش یک تابع با آرگومان های رویدادهای من بنویسه و با یک فانکشن یا هر جوری که میشه اونو بده به Dll من. و Dll من زمانی که میخواست اون ایونت رو اجرا کنه بیاد توابعی که بهش داده شده رو اجرا کنه.
-------------------
اگه بشه این کارو کرد هم مشکل من حل میشه:
من توی Dll خودم یک تایمر داشته باشم که هر ثانیه یکبار اجرا بشه. حالا برنامه نویس بتونه یک تابع درست کنه و اونو بده به Dll من. Dll من هم اون تابع رو بزاره به جای تابع Timer خودش. و هر یک ثانیه یکبار تابع نوشته شده از طرف برنامه نویس اجرا بشه.
------------------
امیدوارم منظورمو رسونده باشم.
بازم تشکر

Mask
شنبه 14 آذر 1394, 14:32 عصر
استفاده از تایمر کار صدردرصد اشتباه و پر مصرفیه. اغلب انتی ویروسها هم بهش گیر میدن.
به نظر من سه راه منطقی و خوب وجود داره:
1- یه تابع به اسم مثلا Start بنویس توی dll با پارامتری از نوع Thandle .خوب برنامه هندل خودش رو ارسال میکنه به dll. الان dll هندل برنامه رو داره و به محض اینکه ایونتهای مورد نظر کال شد با یه SnedMessage وضعیتش رو به برنامه ارسال میکنه. فقط کافیه یه مسیج هندلر در برنامه نوشته بشه و پیغامهای مورد نظر رو دریافت کنه.
2- یه تابع به اسم GetListin بنویس در dll که یه ورودی عددی میگیره. و در برنامه کلاینت یه پورت رو ببر در حالت Listin و همون شماره ای که برای dll ارسال کردی. در dll به محض اینکه ایونت اجرا شد پیامی به پورت باز شده که شمارشم میدونیم ارسال میکنه و اینچوری برنامه اونو دریافت میکنه.
3- استفاده از MemShare که زیاد پیشنهاد نمیدم.
موفق باشید.

یوسف زالی
شنبه 14 آذر 1394, 16:10 عصر
با سلام.
هر رویدادی یک نگهدارنده متد هست، یعنی دارای یک آدرسه، وقتی برای رویداد کد می نویسید، در حقیقت خود دلفی انتساب رو براتون انجام می ده.
در DLL کافیه آدرس یک متد رو به اون پاس بدید تا در مواقع لزوم اون رو فایر کنه. این متد رو در رویداد خود DLL ران کنید.

milad7091
یک شنبه 15 آذر 1394, 10:04 صبح
ممنون از دوستان. مشکلم حل شد.
تکمیل شد فایلم همینجا میزام که اگه کسی نیاز داشت بتونه استفاده کنه.

milad7091
سه شنبه 17 آذر 1394, 08:46 صبح
سلام مجدد.
دوستان من کدهامو تا اینجا رسوندم. فقط مشکلی که الان هست اینه. میتونین ببینین این اررو از چیه؟
کدهای DLL من اینجوره
type
TLineHandUp= Procedure(Sender: TObject; const DeviceIndex, LineNumber,LType: Integer);
THandler=Class
procedure DiveceReceiveData(Sender: TObject; const DeviceIndex: Integer;const DataString: string);
Procedure LineHandUp (Sender: TObject; const DeviceIndex, LineNumber,LType: Integer);

public
Str1: integer;
end;
var
TechnoCaller1: TTechnoCaller;
Handler: THandler;
qwe: integer;
FLineHandUp:TLineHandUp;

Procedure THandler.LineHandUp (Sender: TObject; const DeviceIndex, LineNumber,LType: Integer);
begin
OutputDebugString('Milad1');
FLineHandUp(sender,DeviceIndex,LineNumber,LType);
OutputDebugString('Milad2');
end;

function SetInit(): Boolean;cdecl; export;
begin
qwe:=0;
Handler:=THandler.Create;
TechnoCaller1:= TTechnoCaller.Create(TechnoCaller1);
TechnoCaller1.OnDiveceReceiveData:= Handler.DiveceReceiveData;
TechnoCaller1.Init;
qwe:=qwe+1;
result:= true;
end;

procedure SetLineHandUp(NewEvent: TLineHandUp);cdecl; export;
begin
FLineHandUp:= NewEvent;
TechnoCaller1.OnLineHandUp:= Handler.LineHandUp;
end;
{$R *.res}
exports SetInit,SetCount,SetLineHandUp;
begin

end.





. اینم کد های فانکشن توی برنامه منه.
procedure TForm1.FormCreate(Sender: TObject);
begin
dllHandle := LoadLibrary('C:\Users\Milad\Desktop\TestDllTechnoC aller\Win32\Debug\TestDllTechnoCaller.dll');
if dllHandle <> 0 then
begin
@Init := GetProcAddress(dllHandle, 'SetInit') ;
@SetCount := GetProcAddress(dllHandle, 'SetCount') ;
@LineHandUp := GetProcAddress(dllHandle, 'SetLineHandUp') ;

if Assigned (SetCount) then
begin
if (Init()=true) then
begin
ShowMessage(inttostr(SetCount()));
LineHandUp(form1.TechnoCaller1LineHandUp);
end;
end
else
ShowMessage('"SetInit" function not found') ;
// FreeLibrary(dllHandle) ;
end
else
begin
ShowMessage('TestDllTechnoCaller.dll not found / not loaded');
end;
end;

زمانی که اینتراپت اجرا میشه. پیغام میده
project Project1.exe raised exception class $c000000005 with message 'acccess violation at 0x0012febf: write of address 0x827c7a0d'.
. ممنون میشم ایراد کد منو بگین چیه.