1. เริ่มโครงการ DLL แรกของคุณ
1.File-> ปิด All-> file-> ใหม่ [dll>
รหัส : |
// สร้างรหัสโดยอัตโนมัติดังนี้ โครงการห้องสมุด 2; // นี่เป็นเรื่องไร้สาระ ใช้ Sysutils ชั้นเรียน; {$ r *.res} เริ่ม จบ. |
2. เพิ่ม func เพื่อป้อน:
รหัส : |
โครงการห้องสมุด 2; ใช้ Sysutils ชั้นเรียน; ฟังก์ชั่น mymax (x, y: จำนวนเต็ม): จำนวนเต็ม; เริ่ม ถ้า x> y แล้ว ผลลัพธ์: = x อื่น ผลลัพธ์: = y; จบ ; // โปรดจำไว้ว่า: ชื่อของห้องสมุดไม่สำคัญ แต่กรณีของ DLL-Func เกี่ยวข้องกัน // การเขียน mymax ใน dll-func-name แตกต่างจาก mymax หากเขียนผิดทันที // ผลลัพธ์คือคุณถามว่า AP ที่ใช้ DLL นี้ไม่สามารถเปิดได้เลย // ตัวพิมพ์ใหญ่บนและล่างของพารามิเตอร์ก็โอเค ไม่จำเป็นต้องมีชื่อเดียวกัน ถ้าต้นแบบคือ (x, y: จำนวนเต็ม) // เขียนเป็น (a, b: จำนวนเต็ม) ในเวลาไม่เป็นไร // จำไว้ว่า: เพิ่ม stdcall อื่น หนังสือเล่มนี้บอกว่าถ้าคุณกำลังเขียน DLL โดยใช้ Delphi และหวังว่าจะไม่เพียง แต่จะทำ // ถ้า Delphi-AP หวังว่าจะใช้ BCB/VC-AP ฯลฯ คุณควรเพิ่ม stdcall; // รูปแบบพารามิเตอร์: Delphi มีรูปแบบตัวแปรมากมายซึ่งแน่นอนว่าไม่ใช่สิ่งที่ dll ชอบ // ภาษาพื้นเมืองของ Windows/dll ควรเป็น C. ดังนั้นหากเราต้องการส่งผ่านพารามิเตอร์ของ DLL เรา // ใช้มากที่สุดตามกฎ หากคุณเขียนสองสิ่งนี้หลังจะเป็นปัญหามาก หากคุณไม่คุ้นเคยกับ C // ถ้าไม่เป็นไร เราจะพูดถึงเรื่องนี้ในภายหลัง {$ r *.res} เริ่ม จบ. |
3. ส่ง funcs ที่แชร์ได้เหล่านี้ออกจาก DLL และปล่อยให้โลกภายนอก (เป็นการใช้ delphi-ap ของคุณ): guangru
ดังนั้น AP ของคุณไม่สามารถใช้สิ่งเหล่านี้ได้คุณต้องเพิ่มการส่งออก
รหัส : |
{$ r *.res} การส่งออก mymax; เริ่ม จบ. |
4. โอเคคุณสามารถกด Ctrl-F9 เพื่อรวบรวม อย่ากด F9 ในเวลานี้ DLL ไม่ใช่exe┌ที่ไม่สามารถดำเนินการแยกกันได้ หาก DLL มีข้อผิดพลาดในเวลานี้โปรดแก้ไข กด Ctrl-F9 อีกครั้ง คำเตือนอาจอยู่ที่นั่นในเวลานี้มันไม่สำคัญเพียงแค่ศึกษาและดู กด CTRL-F9 อีกครั้งจากนั้น "เสร็จแล้วรวบรวม" จะมี *.dll ในไดเรกทอรีเดียวกัน ขอแสดงความยินดีงานเสร็จแล้ว
2. ดำเนินการทดสอบ: เปิดแอปพลิเคชันใหม่:
1. เพิ่ม tbutton
รหัส : |
ShowMessage (inttoStr (mymax (30,50))); |
2. บอก Exe ให้ไปที่นั่นเพื่อจับ func
รหัส : |
// เพิ่มลงในฟอร์ม, อินเตอร์เฟส, var ฟังก์ชั่น mymax (x, y: จำนวนเต็ม): จำนวนเต็ม; // mytestdll.dll เขียนชื่อโครงการ DLL ให้คุณก่อน // ไม่สำคัญว่าชื่อ DLL นั้นอยู่บนและล่าง แต่อย่าลืมเพิ่มส่วนขยาย. dll บน win95 หรือ nt // ไม่จำเป็นต้องเพิ่มส่วนขยาย แต่ OSS ทั้งสองนี้อาจน้อยลง คุณต้องเพิ่มส่วนขยาย |
ตกลงมันง่าย
ตัวอย่างข้างต้นง่ายมากหรือไม่? เพื่อนที่คุ้นเคยกับ Delphi สามารถเห็นได้ว่ารหัสข้างต้นนั้นเหมือนกับการเขียนโปรแกรม Delphi ทั่วไปยกเว้นว่ามีพารามิเตอร์ STDCALL เพิ่มเติมหลังจากฟังก์ชั่น TestDll และฟังก์ชั่น TestDll ถูกประกาศโดยใช้คำสั่ง Exports เพียงรวบรวมรหัสด้านบนและคุณสามารถรับไลบรารีลิงก์แบบไดนามิกที่เรียกว่า delphi.dll ทีนี้มาดูกันว่าต้องการความสนใจอะไรบ้าง 1. ฟังก์ชั่นหรือขั้นตอนทั้งหมดที่เขียนใน DLL จะต้องเพิ่มด้วยพารามิเตอร์การโทร STDCALL ในสภาพแวดล้อม Delphi 1 หรือ Delphi 2 พารามิเตอร์การโทรอยู่ไกล หลังจาก Delphi 3 พารามิเตอร์นี้ถูกเปลี่ยนเป็น StdCall โดยมีวัตถุประสงค์เพื่อใช้เทคโนโลยีการถ่ายโอนพารามิเตอร์ Win32 มาตรฐานแทนพารามิเตอร์การลงทะเบียนที่ดีที่สุด ลืมที่จะใช้พารามิเตอร์ stdcall เป็นข้อผิดพลาดทั่วไป เหตุผลก็คือพารามิเตอร์การลงทะเบียนเป็นพารามิเตอร์เริ่มต้นของ Delphi
2. ฟังก์ชั่นและขั้นตอนการเขียนควรประกาศเป็นฟังก์ชั่นภายนอกโดยใช้คำสั่งการส่งออก
อย่างที่คุณเห็นฟังก์ชั่น TestDll ถูกประกาศว่าเป็นฟังก์ชันภายนอก สิ่งนี้ช่วยให้ฟังก์ชั่นสามารถมองเห็นได้จากภายนอก (หากไม่มีตัวเลือกมุมมองที่รวดเร็วคุณสามารถติดตั้งได้จาก Windows CD) ฟังก์ชั่น TestDll จะปรากฏขึ้นในแถบตารางการส่งออก อีกเหตุผลที่ดีคือถ้าเราไม่ประกาศด้วยวิธีนี้ฟังก์ชั่นที่เราเขียนจะไม่ถูกเรียกซึ่งเป็นสิ่งที่ไม่มีใครอยากเห็น
3. เมื่อใช้พารามิเตอร์ประเภทสตริงยาวและตัวแปรควรอ้างอิง Sharemem
ประเภทสตริงใน Delphi นั้นทรงพลังมาก (ใช่คุณอ่านถูกต้องแน่นอนว่าเป็นสองเมกะไบต์) ในเวลานี้ถ้าคุณยืนยันในการใช้พารามิเตอร์ประเภทสตริงตัวแปรหรือแม้แต่ข้อมูลการบันทึกคุณต้องอ้างถึงหน่วย Sharemem และมันจะต้องเป็นข้อมูลอ้างอิงแรก . มันเป็นหน่วยอ้างอิงแรกหลังจากคำสั่งการใช้งาน ดังที่แสดงในตัวอย่างต่อไปนี้:
ใช้
Sharemem
Sysutils
ชั้นเรียน;
อีกประเด็นหนึ่งคือสิ่งเดียวกันควรทำในไฟล์โครงการของคุณ (*.dpr) แทนไฟล์หน่วย (*.pas) หากคุณไม่ทำเช่นนี้คุณมีแนวโน้มที่จะจ่ายค่าผิดพลาด วิธีที่จะหลีกเลี่ยงการใช้ประเภทสตริงคือการประกาศพารามิเตอร์ตัวแปร ฯลฯ ของประเภทสตริงเป็น pchar หรือ shortstring (เช่น: s: string [10]) ประเภท ปัญหาเดียวกันเกิดขึ้นเมื่อคุณใช้อาร์เรย์แบบไดนามิกโซลูชันดังที่อธิบายไว้ข้างต้น
บทที่ 3: การโทรแบบคงที่ไปยัง DLL Top ใน Delphi
การโทรหา DLL นั้นง่ายกว่าการเขียน DLL ก่อนอื่นฉันจะแนะนำวิธีการโทรแบบคงที่ให้คุณ ในทำนองเดียวกันก่อนอื่นให้ยกตัวอย่างการโทรแบบคงที่
บทที่หน่วย 1;
ส่วนต่อประสาน
ใช้
Windows, ข้อความ, sysutils, คลาส, กราฟิก,
การควบคุม, รูปแบบ, กล่องโต้ตอบ, stdctrls;
พิมพ์
tform1 = คลาส (tform)
Edit1: Tedit;
ปุ่ม 1: tbutton;
ขั้นตอน button1click (ผู้ส่ง: tobject);
ส่วนตัว
{ประกาศส่วนตัว}
สาธารณะ
{ประกาศสาธารณะ}
จบ;
วาจา
Form1: TFORM1;
การดำเนินการ
{$ r *.dfm}
// รหัสต่อไปนี้ในบรรทัดนี้คือรหัสที่เราเขียนจริงๆ
ฟังก์ชั่น testdll (i: จำนวนเต็ม): จำนวนเต็ม; stdcall;
ภายนอก 'delphi.dll';
ขั้นตอน tform1.button1click (ผู้ส่ง: tobject);
เริ่ม
edit1.Text: = intToStr (testDll (1));
จบ;
จบ.
ในตัวอย่างด้านบนเราวางกล่องแก้ไข (แก้ไข) และปุ่มบนแบบฟอร์มและเขียนรหัสน้อยมากเพื่อทดสอบ delphi.dll ที่เราเพิ่งเขียน คุณจะเห็นว่างานเดียวที่เราทำคือใส่ส่วนคำอธิบายของฟังก์ชั่น testdll ในการใช้งานและระบุตำแหน่งของ delphi.dll กับคำสั่งภายนอก (ในตัวอย่างนี้โปรแกรมการโทรและ delphi.dll อยู่ในไดเรกทอรีเดียวกัน) มันน่าตื่นเต้นที่ฟังก์ชั่น testdll ที่เราเขียนเองได้รับการยอมรับอย่างรวดเร็วจาก Delphi คุณสามารถทำการทดลองเช่นนี้: ป้อน "testdll (" และในไม่ช้า Delphi จะใช้แถบพรอมต์แบบบินเพื่อแจ้งให้คุณทราบว่าพารามิเตอร์ที่คุณควรป้อนนั้นง่ายพอ ๆ กับการใช้ฟังก์ชั่นอื่น ๆ ที่กำหนดไว้ใน Delphi บันทึกรวม
ต่อไป:
1. ใช้ stdcall เพื่อเรียกพารามิเตอร์
ดังที่ได้กล่าวไว้ข้างต้นเมื่ออ้างถึงฟังก์ชั่นและขั้นตอนใน DLL คุณต้องใช้พารามิเตอร์ stdcall ด้วยเหตุผลเดียวกับที่กล่าวไว้ข้างต้น
2. ใช้คำสั่งภายนอกเพื่อระบุเส้นทางและชื่อของไฟล์ DLL ที่เรียกว่า
อย่างที่คุณเห็นเราระบุชื่อของไฟล์ DLL ที่จะเรียกในคำสั่งภายนอก ไม่มีเส้นทางการเขียนเนื่องจากไฟล์ DLL และโปรแกรมหลักที่เรียกว่าอยู่ในไดเรกทอรีเดียวกัน หากไฟล์ DLL อยู่ใน C:/เราสามารถเขียนคำสั่งอ้างอิงข้างต้นเป็นภายนอก 'C: /delphi.dll' โปรดทราบว่าจะต้องเขียนคำต่อท้ายของไฟล์
3. ตัวแปรทั่วโลกไม่สามารถเรียกได้จาก DLL
ถ้าเราประกาศตัวแปรทั่วโลกบางชนิดใน DLL เช่น: var s: byte ด้วยวิธีนี้ตัวแปรทั่วโลกสามารถใช้งานได้ตามปกติใน DLL แต่ไม่สามารถใช้งานได้โดยโปรแกรมการโทรและ S ไม่สามารถส่งผ่านเป็นตัวแปรส่วนกลางไปยังโปรแกรมการโทร อย่างไรก็ตามตัวแปรที่ประกาศในโปรแกรมการโทรสามารถส่งผ่านเป็นพารามิเตอร์ไปยัง DLL
4. ต้องมี DLL ที่เรียกว่า
นี่เป็นสิ่งสำคัญ หากไม่มีพา ธ และชื่อไฟล์ที่ระบุหรือชื่อพา ธ และชื่อที่ระบุไม่ถูกต้องระบบจะแจ้ง "เกิดข้อผิดพลาดในขณะที่เริ่มโปรแกรม" หรือ "ไม่พบ *.dll ไฟล์" เมื่อเรียกใช้โปรแกรมหลัก
บทที่ 4 การเรียก DLL แบบไดนามิกใน Delphi
การโทรแบบไดนามิก DLLS ค่อนข้างซับซ้อน แต่มีความยืดหยุ่นมาก เพื่อแสดงให้เห็นถึงปัญหาอย่างละเอียดคราวนี้เราให้ตัวอย่างของการโทรหา DLL ที่เขียนใน C ++ ขั้นแรกให้รวบรวมโปรแกรมแหล่ง DLL ต่อไปนี้ใน C ++
#รวม
extern "C" _DeclSpec (dllexport)
int winapi testc (int i)
-
กลับฉัน;
-
หลังจากการรวบรวมไฟล์ DLL ถูกสร้างขึ้นที่นี่เราเรียกไฟล์นี้ CPP.DLL เพื่อความสะดวกเรายังคงอ้างถึงโปรแกรมการโทรข้างต้น แต่แทนที่คำสั่งดั้งเดิมในกระบวนการ Button1Click ด้วยรหัสต่อไปนี้
ขั้นตอน tform1.button1click (ผู้ส่ง: tobject);
พิมพ์
tintfunc = ฟังก์ชั่น (i: จำนวนเต็ม): จำนวนเต็ม; stdcall;
วาจา
Th: Thandle;
TF: Tintfunc;
TP: tfarproc;
เริ่ม
th: = loadlibrary ('cpp.dll');
ถ้า th> 0 แล้ว
พยายาม
tp: = getProcaddress (th, pchar ('testc'));
ถ้า tp <> nil
จากนั้นเริ่มต้น
tf: = tintfunc (tp);
edit1.Text: = intToStr (tf (1));
จบ
อื่น
showmessage ('ฟังก์ชั่น TESTC ไม่พบ');
ในที่สุด
FreeLibrary (TH);
จบ
อื่น
showmessage ('cpp.dll ไม่พบ');
จบ;
อย่างที่คุณได้เห็นเทคนิคการโทรแบบไดนามิกนี้มีความซับซ้อนมาก แต่ตราบใดที่คุณปรับเปลี่ยนพารามิเตอร์เช่นการแก้ไขชื่อ DLL ใน LoadLibrary ('CPP.DLL') เป็น 'Delphi.dll' คุณสามารถเปลี่ยนแบบไดนามิก เรียกว่า DLL
1. กำหนดประเภทของฟังก์ชั่นหรือขั้นตอนที่จะเรียก
ในรหัสข้างต้นเรากำหนดประเภท tintfunc ซึ่งสอดคล้องกับฟังก์ชั่น testc ที่เราจะโทร คำจำกัดความเดียวกันควรทำในการโทรอื่น ๆ และเพิ่มพารามิเตอร์การโทร stdcall
2. ปล่อย DLL ที่เรียกว่า
เราเรียกว่า DLL แบบไดนามิกด้วย LoadLibrary แต่โปรดจำไว้ว่าคุณต้องปล่อย DLL ด้วย FreeLibrary ด้วยตนเองหลังการใช้งานมิฉะนั้น DLL จะใช้หน่วยความจำจนกว่าคุณจะออกจากหน้าต่างหรือปิดตัวลง
ตอนนี้มาประเมินข้อดีและข้อเสียของทั้งสองวิธีในการโทร DLL วิธีการคงที่นั้นง่ายต่อการใช้งานง่ายต่อการควบคุมและโดยทั่วไปเร็วกว่าเล็กน้อยและปลอดภัยกว่าและเชื่อถือได้มากขึ้น ในการทำงานจนกว่า DLL จะถูกปล่อยออกมาเฉพาะตอนท้ายของโปรแกรมและเฉพาะระบบที่ใช้คอมไพเลอร์เช่น Delphi เท่านั้นที่สามารถใช้วิธีนี้ได้ วิธีการไดนามิกดีกว่าแก้ปัญหาในวิธีการคงที่และสามารถเข้าถึงฟังก์ชั่นและขั้นตอนใน DLLs ได้อย่างง่ายดายและแม้แต่ฟังก์ชั่นหรือขั้นตอนที่เพิ่มขึ้นใหม่ใน DLLs รุ่นเก่าบางรุ่น ฟังก์ชั่นหรือขั้นตอนจำเป็นต้องกำหนดประเภทที่ซับซ้อนและวิธีการโทร สำหรับผู้เริ่มต้นผู้เขียนแนะนำให้คุณใช้วิธีการคงที่จากนั้นใช้วิธีการโทรแบบไดนามิกหลังจากที่คุณมีความเชี่ยวชาญ
บทที่ 5 เคล็ดลับการใช้งานจริงสำหรับการใช้ DLL TOP
1. ทักษะการเขียน
1. เพื่อให้แน่ใจว่าความถูกต้องของ DLL คุณสามารถเขียนมันเป็นส่วนหนึ่งของแอปพลิเคชันทั่วไปทำการดีบักอย่างถูกต้องแล้วแยกออกจากโปรแกรมหลักและรวบรวมเป็น DLL
2. เพื่อให้แน่ใจว่าความเป็นสากลของ DLL คุณควรป้องกันชื่อของการควบคุมภาพจากการปรากฏตัวใน DLL ที่คุณเขียนด้วยตัวเองเช่น: Edit1 ชื่อใน Edit1.Text; บันทึกบางอย่าง
3. เพื่ออำนวยความสะดวกในการดีบักแต่ละฟังก์ชั่นและกระบวนการควรสั้นและกระชับที่สุดเท่าที่จะทำได้และควรมาพร้อมกับคำอธิบายประกอบที่เฉพาะเจาะจงและรายละเอียด
4. ควรใช้การทดลองในที่สุดเพื่อจัดการกับข้อผิดพลาดและข้อยกเว้นที่เป็นไปได้
5. การอ้างอิงเพียงไม่กี่หน่วยเท่าที่จะทำได้เพื่อลดขนาดของ DLL โดยเฉพาะอย่างยิ่งไม่ได้อ้างถึงหน่วยภาพเช่นหน่วยโต้ตอบ ตัวอย่างเช่นโดยทั่วไปเราไม่สามารถอ้างอิงหน่วยคลาสซึ่งสามารถลด DLL ที่รวบรวมได้ประมาณ 16KB
2. ทักษะการโทร.
1. เมื่อใช้วิธีการคงที่คุณสามารถเปลี่ยนชื่อฟังก์ชันหรือขั้นตอนที่เรียกว่า ในตัวอย่าง DLL ที่เขียนใน C ++ ที่กล่าวถึงข้างต้นหากคำสั่ง "C" ภายนอกถูกลบออก C ++ จะรวบรวมชื่อฟังก์ชั่นแปลก ๆ และฟังก์ชั่น TESTC ดั้งเดิมจะถูกตั้งชื่อ @testc $ s และชื่อแปลก ๆ อื่น ๆ ใช้เทคโนโลยี Mangling ชื่อ C ++ ชื่อฟังก์ชันนี้ผิดกฎหมายใน Delphi เราสามารถแก้ปัญหานี้ได้เช่นนี้:
เขียนฟังก์ชั่นอ้างอิงใหม่เป็น
ฟังก์ชั่น testc (i: จำนวนเต็ม): จำนวนเต็ม; stdcall;
ภายนอก 'cpp.dll'; ชื่อ '@testc $ s';
ฟังก์ชั่นของชื่อคือการเปลี่ยนชื่อ
2. คุณสามารถใส่ DLL ที่เราเขียนไว้ในไดเรกทอรี Windows หรือไดเรกทอรี Windows/System การทำเช่นนั้นสามารถเขียนได้เฉพาะชื่อของ DLL โดยไม่ต้องเขียนเส้นทางในคำสั่งภายนอกหรือในคำสั่ง loadlibrary แต่มันก็ไม่เหมาะสมที่จะทำเช่นนี้ ใส่ dlls ที่คุณเขียนลงไปในไดเรกทอรีระบบ!
3. ทักษะการดีบัก
1. เรารู้ว่า DLL ไม่สามารถเรียกใช้และดีบักทีละขั้นตอนเมื่อเขียน มีวิธีการทำเช่นนี้นั่นคือตั้งค่าโปรแกรมโฮสต์ในเมนูการเรียกใช้ | พารามิเตอร์ เพิ่มชื่อของโปรแกรมโฮสต์ลงในแถบแอปพลิเคชันโฮสต์ของหน้าท้องถิ่นเพื่อทำการดีบักทีละขั้นตอนการสังเกตและการทำงานของเบรกพอยต์
2. เพิ่มข้อมูลเวอร์ชัน DLL ข้อสังเกตการเปิดกล่าวว่าข้อมูลเวอร์ชันมีความสำคัญมากสำหรับ DLL มันคุ้มค่าที่จะเพิ่มพื้นที่เล็ก ๆ น้อย ๆ น่าเสียดายที่ไม่สามารถใช้ตัวเลือกเวอร์ชันในเมนูโครงการ | ตัวเลือกได้โดยตรง ดังที่แสดงในตัวอย่างต่อไปนี้:
ห้องสมุด Delphi;
ใช้
Sysutils
ชั้นเรียน;
{$ r *.res}
// โปรดทราบว่าต้องเพิ่มบรรทัดด้านบนของรหัสในตำแหน่งนี้
ฟังก์ชั่น testdll (i: จำนวนเต็ม): จำนวนเต็ม; stdcall;
เริ่ม
ผลลัพธ์: = i;
จบ;
การส่งออก
testdll;
เริ่ม
จบ.
3. เพื่อหลีกเลี่ยงการทำซ้ำชื่อกับ DLL อื่น ๆ ควรใช้การผสมผสานของอักขระตัวเลขและขีดเส้นใต้เมื่อตั้งชื่อ DLL ที่คุณเขียน ตัวอย่างเช่น: jl_try16.dll
4. หากคุณได้รวบรวม DLL บางตัวใน Delphi 1 หรือ Delphi 2 แล้ว DLL ที่คุณรวบรวมคือ 16 บิต เพียงแค่คอมไพล์ซอร์สโค้ดใหม่ในสภาพแวดล้อม Delphi 3 หรือ Delphi 4 ใหม่อีกครั้งและคุณสามารถรับ DLL 32 บิตได้
[หลังจากหมายเหตุ]: นอกเหนือจากวิธีการที่ใช้กันมากที่สุดในการใช้ DLL ที่แนะนำข้างต้นแล้ว DLL ยังสามารถใช้เป็นผู้ให้บริการทรัพยากรได้ ตัวอย่างเช่นการเปลี่ยนไอคอนใน Windows เป็นทรัพยากรใน DLL ที่ใช้ นอกจากนี้การมีเทคโนโลยีการออกแบบ DLL ที่เชี่ยวชาญมีประโยชน์มากมายสำหรับการใช้โปรแกรม OLE, COM และ ActiveX ขั้นสูง