إنشاء وإستدعاء الـ DLLs من دلفي

بداية مبسطة عن :

مكتبات الربط الديناميكية
dll
........................
مكتبات الربط الديناميكية هي ملفات موارد منفصلة ومستقلة ... يمكن استخدامها في أي لغة برمجة , وعادة ما تستخدم لتزويد برامجنا التنفيذية بالتوابع والإجراءات التي نكتبها بها , ومختلف أنواع الموارد الأخرى (حتى أننا نستطيع تضمينها صور وأصوات وفديو إذا أردنا) .وما قصدتة بعبارة أنها موارد مستقلة يعني أن المكتبات التي نصممها باستخدام ديلفي يمكن استخدامها في أي لغة برمجة أخرى c++ مثلا وبالعكس كذلك , فهي مستقلة عن الملف التنفيذي ويتم إستدعائها أثناء التنفيذ , والجدير بالذكر أنة لو قامت عدة ملفات تنفيذية بإستدعاء نفس مكتبة الربط الديناميكية فإن نسخة واحدة فقط تكفي أن تكون مخزنة على القرص أو محملة على الذاكرة .
وبالطبع يمكن لمكتبات ربط ديناميكية أن تستخدم مكتبات ربط ديناميكية أخرى أيضا وتستدعيها ..

مثال بسيط :
نقوم مثلا بكتابة مكتبة ربط تحتوي على جميع التوابع الرياضية : كتابع التربيع و تابع الجذر و .. و .... الخ ثم نقوم باستدعاء هذة التوابع من برامجنا ....

لن أتكلم عن فوائد هذة المكتبات وفوائد فصل الإجرائيات والموارد عن البرنامج الأساسي وسوف اتكلم بإيجاز عن كيفية بنائها واستدعائها من ديلفي .


**********************************************

1- انشاء مكتبة ربط ديناميكية :
---------------------------------

من القائمة إختر ....

file -> new -> other -> dllwizard .
سوف ترى الوحدة بالشكل التالي :

library Project2;


uses
SysUtils,
Classes;

{$R *.res}

begin
end.

والإستخدام سهل وبسيط جدا ,, نكتب الإجراءات والتوابع التي نريدها ,مثلما نكتبها في الحالة العادية
بعض هذة الإجراءات محلي فقط حيث يقوم بإتمام عمل إجراءات أخرى .
وبعضها الآخر يجب جعله متاحا للبرامج الأخرى , ونعبر عن ذلك بإنة قابل للتصدير Export ,.
بعد كتابة التوابع يجب تحديد التوابع القابلة للتصدير , وذلك بإضافة الكلمة المحجوزة Exports وبعدها أسماء التوابع التي نريد تصديرها .
مثال بسيط :
إستبدل الموجود في الوحدة الجاهزة بالشفرة البسيطة التالية :


library dllfile;

uses
SysUtils,dialogs,
Classes;
{
إستخدمنا الوحدة Dialogs من أجل التابع Showmessage
}


{$R *.res}

procedure hello; //نفس طريقة كتابة الإجراء العادي .
begin
showmessage('hello world . . . ');
end;

exports
hello ;
end.


ثم من
Project -> compile
Project -> build

**
لاحظ أننا أضفنا العبارة exports بمعنى تصدير وأضفنا بعدها اسماء التوابع والاجراءات التي تريد أن نسمح للبرامج الأخرى بالوصول إليها من الـ DLL .. أي التي سوف نستخدمها في برنامجنا التنفيذي .


************************************************

2- استدعاء المكتبة من البرنامج
---------------------------------

نستطيع ببساطة استدعاء توابع المكتبة التي صنعناها أو التي صنعها غيرنا , في أي مكان من الشفرة ,
ولكن علينا أولا التصريح أن هذة التوابع موجودة في ملف خارجي هو مكتبة الربط الديناميكية لكي نعلم دلفي بضرورة جلبها من خارج الشفرة .
*****
هناك نوعين من الإستدعاءات :
*- إستدعاء ستاتيكي , وهو الإستدعاء العادي البسيط , حيث يحاول الملف التنفيذي البحث عن ملف الربط الديناميكي أثناء الإقلاع , فإن لم يجدة لا يعمل برنامجنا ويعطينا خطـأ . كما أنة لا يمكننا تغيير التابع المستخدم أو تغيير ملف الربط الديناميكي أثناء التشغيل , أو تحديد متى نحمل تابع معين أو ملف من المكتبة ومتى نحررة فهو يرتبط مع البرنامج أثناء الإقلاع ويتحرر عند الإغلاق , وهذ النوع بشكل عام الأكثر إستخداما وخاصة للحالات البسيطة , لإن العيوب السابقة نادرا ما نضطر لإستخدامها في البرامج العادية .
*- الإستدعاء الديناميكي , وهو بالطبع لة ميزات إضافية كثيرة عن سابقة . وقد يكون من الضروري في بعض الأحيان إستخدام هذا النوع من الإستدعاءات .. ومن ميزاتة أنة يمكننا تحديد ملف الDll أو تابع معين من الملف أثناء التشغيل , ونقوم بتحميل الملف ( ربطة الى البرنامج ) في أي وقت نشاء عكس الحالة السابقة . كما أنة بإمكاننا تحريرة عندما نشاء ,, الخ ...


وسنستدعي الآن مثالنا السابق باستخدام النوع البسيط الأول :

الإستدعاء الساكن :
***********
علينا أولا التصريح أن هذة التوابع موجودة في ملف خارجي هو مكتبة الربط الديناميكية بالشكل التالي :


procedure ProcName ; external 'dllfileName';

...................................................................................

مثال : لإستدعاء المكتبة التي صنعناها منذ قليل


implementation
{$R *.dfm}

procedure hello ; external 'dllfile.dll'; // نضيف التعريف عن رأس التابع

procedure TForm1.Button1Click(Sender: TObject);
begin
hello;
end;

end.



بكل بساطة نعرف عن إسم التابع في البداية , وعلى أنة ملف خارجي External ثم نستخدم التابع في أي منطقة من الشفرة ساعة نشاء ..

الإستدعاء الديناميكي :
****************
تقوم فكرة هذا النوع من الإستدعاءات , على تحديد إسم الملف وإسم التابع (الإجرائية ) الذين نريد إستخدامهما أثناء التشغيل .
وبالتالي يمكننا التعامل مع ذلك بمرونة تامة . مثلا يمكننا ذلك من إختيار ملف ال Dll الذي نريد تحميل تابعنا منة .
ولنفرض أننا نريد القيام بإجرائية معينة تختلف نتائجها حسب نظام التشغيل الذي تعمل علية . فإننا عند ذلك نبني لكل إصدارة من نظام التشغيل ملف DLL خاص وجميع الملفات تحوي نفس أسم التابع المراد , وعند تشغيل البرنامج يقرأ إصدارة النظام الحالية , ويقوم بإستدعاء التابع المطلوب من الملف الخاص بالإصدارة الحالية ..)
أو يمكننا تحديد التابع الذي نريد إستدعائة أثناء التشغيل أيضا , وهي أيضا ميزة سحرية ..
كما أنة يمكننا تحميل الملف في أي لحظة وبالتالي لن نضطر لتحميلة كل مرة منذ بدء تشغيل البرنامج , كما أنة في حالة ملف ال DLL لم يكن موجودا فعندها لن يمتنع برنامجنا عن الإقلاع , بل سيقلع مثل العادة ولكنة لن يستطيع تنفيذ الإجراء الموجود بالملف المفقود .
مثال :
لنقوم بإستدعاء التابع السابق Hello من الملف dllfile المعمول مسبقا , ولكن هذة المرة بالطريقة الديناميكية .
1- نضيف متحول من الصنف Procedure ومتحول من الصنف Thandle :

type THelloshowtype=procedure
..
..
..
private
Helloshow:THelloshowtype; // متحول من أجل الإجراء
dllhandle:Thandle; //متحول من أجل ملف الربط الديناميكي

المتحول الأول سوف ننسب إلية الإجراء الذي نريد إستدعائة .
المتحول الثاني ننسب إلية ال DLL الذي يحوي الإجراء .

2- من أجل تحميل المكتبة والتابع , نكتب الشفرة التالية :

procedure TForm1.Button2Click(Sender: TObject);
begin
dllhandle:=LoadLibrary('dllfile.dll'); //تحميل المكتبة
@Helloshow:=GetProcAddress(dllhandle,'hello');//تحميل الإجرائية
end;

3- من أجل إستدعاء التابع :
مثل العادة نكتب :

procedure TForm1.Button1Click(Sender: TObject);
begin
Helloshow; // إستدعاء الإجرائية مثل العادة
end;

4- من أجل تحرير المكتبة :

procedure TForm1.Button3Click(Sender: TObject);
begin
FreeLibrary(dllhandle); // تحرير المكتبة
end;

وكما لاحظنا يمكننا فصل كل إجراء من الأجراءات السابقة لوحدة وإستدعائة إينما نريد مما يضاعف من مرونة إستدعاء المكاتب وتوابعها بشكل كبير ..

ملاحظات :

في لغــة C++ لم تكن قد ظهرت الإجرائيات Procedures , لذلك إذا كنت تتوقع استخدام المكتبة من C++ إستخدم التوابع Functions فقط ..

إذا أردنا إستخدام أي مكتبة ربط ديناميكة , علينا أولا معرفة أسماء التوابع العامة الموجودة بها وبرامترات كل منها لكي نستطيع إستدعائها .

قد تختلف بعض البرامترات من لغة برمجة إلى أخرى ,, وعندئذ يجب مراجعة جداول خاصة لمعرفة التغيرات بالإستدعاء بين اللغات المختلفة

...
أتمنى أن تكون هذة المقالة , مبسطة إلى حد ما , ومفيدة ..
وكل من يملك معلومات مهمة من الأخوة حول هذا الموضوع , فلينشرها لكي نتناقش بها جميعا , ونتتم الفائدة .
وشكرا ,,, أخوكم عروة عيسى
_________________

رابط للأمثلة السابقة مع الشفرة :
مثال بناء ملف Dll
مثال إستدعاء ستاتيكي
مثال استدعاء ديناميكي
الرابط :
http://www.angelfire.com/mac/orwa/DLLFiles.zip





[ تم تحريره بواسطة orwa on 23/12/2003 ]
المنتديات

إضافة تعليق جديد

لا يسمح باستخدام الأحرف الانكليزية في اسم المستخدم. استخدم اسم مستخدم بالعربية

Restricted HTML

  • وسوم إتش.تي.إم.إل المسموح بها: <a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • تفصل السطور و الفقرات تلقائيا.
  • Web page addresses and email addresses turn into links automatically.

دعوة للمشاركة

موقع الأيهم صالح يرحب بالمشاركات والتعليقات ويدعو القراء الراغبين بالمشاركة إلى فتح حساب في الموقع أو تسجيل الدخول إلى حسابهم. المزيد من المعلومات متاح في صفحة المجتمع.