PDA

View Full Version : کلاس در dll



lord_viper
دوشنبه 21 آبان 1386, 15:16 عصر
با سلام
ایا میشه یک کلاس رو تو dllپیاده سازی کرد که کاربر بتونه متد create اون کلاس رو از داخل dllفراخونی کنه و از توابعش استفاده کنه؟
با تشکر

vcldeveloper
سه شنبه 22 آبان 1386, 01:03 صبح
برای این کار می تونید یک Interface تعریف کنید که بین پروژه ایی که از DLL استفاده میکنه و خود DLL مشترکا استفاده بشه:


unit uTestInt;

interface

type
ITest = interface
function Add(a,b: real): real;
procedure TestProc;
end;

implementation

end.
* این یونیت یک اینترفیس ساده با دو متد تعریف میکنه. این یونیت باید در هر دو پروژه use بشه.

حالا باید یک کلاس در DLL تعریف کنید که متدهای Interface بالا را پیاده سازی کنه. یک تابع هم باید بنویسید که یک نمونه از این کلاس ایجاد کنه و نتیجه را بصورت Interface بالا (در این مثال ITest) برگردونه:


library dllTest;

uses
SysUtils,
uTestInt in 'uTestInt.pas';

{$R *.res}
type
TTest = class(TInterfacedObject,ITest)
public
function Add(a,b: real): real;
procedure TestProc;
end;

{ TTest }

function TTest.Add(a, b: real): real;
begin
Result := a + b;
end;

procedure TTest.TestProc;
begin
//nothing;
end;

//////////////////////////////////////
function CreateTest: ITest; stdcall;
begin
Result := TTest.Create;
end;

exports
CreateTest;

begin
end.
* دقت کنید که تابع CreateTest نتیجه را بصورت ITest برمی گردان (اینترفیس)د، نه TTest.

در مرحله آخر هم باید در پروژه ایی که از DLL استفاده می کند، یونیتی که تعریف اینترفیس در آن است را به لیست uses اضافه و تابع CreateTest را تعریف کنید:


function CreateTest: ITest; stdcall; external 'dllTest.dll' name 'CreateTest';

حالا با ایجاد یک متغیر از نوع ITest و نسبت دادن خروجی تابع CreateTest به آن، می توانید یک نمونه از اینترفیس ITest که توسط کلاس TTest در dllTest.dll پیاده سازی شده است، داشته باشید. کد کامل پروژه:


unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls,
uTestInt;

type
TForm1 = class(TForm)
Button1: TButton;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
{ Private declarations }
public
Test : ITest;
end;

function CreateTest: ITest; stdcall; external 'dllTest.dll' name 'CreateTest';
var
Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
Test := CreateTest;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
R : real;
begin
if Assigned(Test) then
begin
R := Test.Add(2,2);
ShowMessage(FloatToStr(R))
end;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
Test := nil;
end;

end.

* دقت کنید که نمونه ایی از ITest که ساختیم و به متغیر Test اختصاص دادیم، هیچوقت Free نشد، بلکه فقط مقدار Test را برابر با nil کردیم. علتش هم استفاده از Interface است. نوع Interface در دلفی Reference-counted هست و بطور خودکار آزاد می شود.
بجای Interface می تونستید از نوع های دیگه هم استفاده کنید:
1- Pointer: در صورت استفاده از Pointer کد ساده تر می شد، اما باید مقدار برگشت داده شده از تابع CreateTest را به کلاس مورد نظر خود Type Cast می کردید. و امکان استفاده از Code Completion هم در زمان کدنویسی نداشتید. Object ایجاد شده هم باید توسط یک تابع دیگر Free می شد.
2- استفاده از Abstract Class. در دلفی Abstract Class وجود نداره، ولی می تونید کلاسی تعریف کنید که تمام متدهای آن Virtual و Abstract باشند. در صورت استفاده از این روش، تمام مزایای استفاده از Interface به غیر از Free شدن خودکار را داشتید.

البته تمام این ها در صورتی است که مجبور به استفاده از DLL باشید، وگرنه با استفاده از Package ها در دلفی می توان به راحتی یک کلاس را پیاده سازی کرد و از آن استفاده کرد.

Inprise
سه شنبه 22 آبان 1386, 01:14 صبح
جواب علی کشاورز خیلی جواب خوبی هست
غیر از اون در کل وقتی داری از bpl ها استفاده میکنی در حال استفاده از کلاسهائی هستی که جای دیگری تعریف و ارائه شدن . استفاده از bpl ها بخاطر روتینهای داخلی دلفی و وی سی ال خیلی راحت و قابل توصیه هستش . bpl در عمل یه جور dll هست بهر حال .

lord_viper
جمعه 25 آبان 1386, 08:38 صبح
ممنونم اگه یک نفر دیگه در یک زبان برنامهنویسی دیگه بخواهد از این dll استفاده کنه چکار باید بکنه؟
با تشکر

Inprise
جمعه 25 آبان 1386, 16:47 عصر
- استفاده از BPL ها در بقیه محیطها کار ساده ای نیست و مسائل زیادی برای حل کردن وجود داره . قابل توصیه نیست مگر از سر اجبار . VCL For VC (http://www.mitov.com/html/vcl_for_vc__.html) اینکار رو به خوبی انجام میده .

- از کلاسهای دلفی به این شکل نمیتونی در بقیه زبونها استفاده کنی . میتونی هر چه لازم داری بصورت تابع اکسپورت کنی و همه جا قابل استفاده (http://www.esanu.name/delphi/DLL/Calling%20delphi%20DLL%20from%20MS%20Visual%20C.ht ml) است . اگر به نوشتن کلاسهای قابل انتقال علاقه داری باید به COM فکر کنی که اصلا به همین منظور طراحی شده . ( و اگر اهل دات نت هستی ، دات نت )