เมื่อเร็ว ๆ นี้ฉันเริ่มทำงานกับ Delphi และพบว่ามีการใช้แพ็คเกจจำนวนมากในโปรแกรมดั้งเดิม แต่ฉันมักจะอยู่ในสถานะที่ไม่รู้ อาจใช้เวลาสักครู่ในการศึกษาปัญหานี้ ดังนั้นรายการคำถามที่ต้องวิเคราะห์ก่อนอื่น:
กระเป๋าคืออะไร? EXE คืออะไร? ความแตกต่างขององค์ประกอบของพวกเขาคืออะไร? ความสัมพันธ์ระหว่างแพ็คเกจและ DCU คืออะไร? DCP ทำอะไร? ความสัมพันธ์ระหว่างไฟล์เหล่านี้ในเวลาคอมไพล์คืออะไร? มันโหลดอย่างไร? วิธีการใช้งานแพ็คเกจหลังจากโหลด? DLL สามารถส่งออกได้ แต่ทำไม Delphi จึงช่วยไม่ให้ส่งออกแพ็คเกจ แต่รหัสบางอย่างใช้ exprots ในแพ็คเกจ
ก่อนอื่นมาดูกระบวนการรวบรวมของ Delphi มีสองประเภทของโครงการใน Delphi: แพ็คเกจและโปรแกรม เริ่มต้นด้วยสิ่งที่เรียบง่ายมาเริ่มด้วย DPR ตามเอกสารช่วยเหลือของ Delphi โครงสร้างของไฟล์ DPR ทั่วไปมีดังนี้:
1 โปรแกรมแก้ไขโปรแกรม;
2
3 ใช้
4 รูปแบบ {เปลี่ยนเป็น qforms ใน Linux}
5 reabout ใน 'reabout.pas' {aboutbox}
6 ยังคงอยู่ใน 'retent.pas' {mainform};
7
8 {$ r *.res}
9
10 เริ่มต้น
11 application.title: = 'ตัวแก้ไขข้อความ';
12 application.createform (tmainform, mainform);
13 Application.run;
14 End.
ในหมู่พวกเขา 10 ถึง 14 บรรทัดเริ่มต้น…จบคือการเข้าสู่การดำเนินการของโปรแกรมโดยธรรมชาติ ส่วนการใช้งานระบุว่าบางหน่วยที่โปรแกรมจำเป็นต้องใช้ซึ่งค่อนข้างคลุมเครือ ความต้องการ? จากนั้นแต่ละหน่วยจะใช้หน่วยอื่น ๆ และปัญหานี้ดูเหมือนจะซับซ้อนมากขึ้นเรื่อย ๆ มาดูโครงสร้างของซอร์สโค้ดทั้งหมดก่อน:
ฉันเดาว่าขั้นตอนแรกของคอมไพเลอร์คือการสำรวจกราฟที่กำกับนี้รวบรวมแต่ละหน่วยถ้าจำเป็นและสร้าง DCU ที่เกี่ยวข้อง สำหรับปัญหา "จำเป็น" นี้ในตอนแรกฉันคิดว่าคำแถลงการใช้งานของหน่วยอยู่ใน แต่ต่อมาฉันพบว่ามันผิด เนื่องจากในกรณีข้างต้น UNIT3 ไม่ได้ระบุเส้นทางในประโยคการใช้งานของ UNIT1 แต่ไฟล์ DCU ที่สอดคล้องกันยังคงถูกสร้างขึ้นอย่างถูกต้อง ต่อมา Filemon ใช้เพื่อตรวจสอบสถานการณ์การเปิดไฟล์และกระบวนการค้นพบมีดังนี้: สำหรับแต่ละโหนดในกราฟคอมไพเลอร์จะค้นหาโหนดที่เกี่ยวข้องในเส้นทางการค้นหาในไดเรกทอรีปัจจุบัน - แอตทริบิวต์โครงการ - เส้นทางไลบรารีในไลบรารี สภาพแวดล้อม
ตอนนี้การรวบรวมเสร็จสิ้นแต่ละหน่วย (เช่นไฟล์ PAS) ได้สร้างไฟล์ DCU สำหรับมัน เมื่อพูดถึงการเชื่อมต่อปัญหามีความซับซ้อน การเชื่อมต่อแบบคงที่หมายถึงการรวม DCU เหล่านี้เข้าด้วยกัน ด้วยวิธีนี้การโทรของหน่วยหนึ่งไปยังหน่วยอื่นกลายเป็นเรื่องภายในของโปรแกรม ประโยชน์นี้คือมันเร็วและง่ายและปัญหาเช่นการแบ่งปันพร้อมกันนั้นง่ายต่อการจัดการ ข้อเสียคือโปรแกรมเป้าหมายมีขนาดใหญ่และหากมีการเขียนโปรแกรมอื่นตอนนี้และสามารถนำกลับมาใช้ใหม่ได้อีกครั้งและสามารถนำมาใช้ซ้ำได้อีกครั้ง UNIT3.DCU จะถูกคัดลอกอีกครั้งเมื่อเชื่อมต่อ ด้วยวิธีนี้เมื่อสองโปรแกรมทำงานในเวลาเดียวกันจะมีสำเนาของหน่วย 3 ในหน่วยความจำสองชุดซึ่งเป็นของเสีย การเชื่อมต่อแบบไดนามิกหมายความว่าเมื่อสองโปรแกรมเชื่อมต่อพวกเขาจะยังคงอ้างอิงถึง UNIT3 เท่านั้นและไม่คัดลอกเนื้อหาของ Unit3 ที่รันไทม์ให้โหลด UNIT3 ลงในหน่วยความจำและทำให้ทั้งสองโปรแกรมทั่วไป DLL และ BPL เป็นทั้งโซลูชั่นสำหรับการเชื่อมต่อแบบไดนามิก ปัญหาคือตัวเลือกเดียวสำหรับการเชื่อมต่อใน Delphi ปรากฏในโครงการ | ตัวเลือก | แพ็คเกจเมนูและประโยค "สร้างด้วยแพ็คเกจรันไทม์" นั้นคลุมเครือเกินไป ดังนั้นเราต้องศึกษาอีกครั้ง
เมื่อโปรแกรมถูกดำเนินการเราสามารถใช้มุมมอง | หน้าต่างดีบัก | Moudles เพื่อดูว่าสิ่งใดที่โหลดลงในหน่วยความจำและเนื้อหาที่มีอยู่
เพื่อให้ง่ายเราตั้งค่าโปรแกรมที่มีโครงสร้างต่อไปนี้:
โปรแกรม ProjectExe;
ใช้
แบบฟอร์ม
หน้าต่าง
UNITFORMMAIN ใน 'UNITFORMMAIN.PAS' {FormMain};
{$ r *.res}
เริ่ม
Application.initialize;
application.createform (tformmain, formmain);
Application.run;
จบ.
UNIT UNITFORMMAIN;
ส่วนต่อประสาน
ใช้
Windows, stdctrls, แบบฟอร์ม, Unitformanother, คลาส, การควบคุม;
พิมพ์
tformmain = คลาส (tform)
ปุ่ม 1: tbutton;
ขั้นตอน button1click (ผู้ส่ง: tobject);
ส่วนตัว
{ประกาศส่วนตัว}
สาธารณะ
{ประกาศสาธารณะ}
จบ;
วาจา
Formmain: tformmain;
การดำเนินการ
{$ r *.dfm}
ขั้นตอน tformmain.button1click (ผู้ส่ง: tobject);
วาจา
lform: tformanother;
เริ่ม
lform: = tformanother.create (แอปพลิเคชัน);
lform.showmodal;
lform.free;
จบ;
จบ.
หน่วยหน่วย
ส่วนต่อประสาน
ใช้
แบบฟอร์ม;
พิมพ์
tformanother = class (tform)
ส่วนตัว
{ประกาศส่วนตัว}
สาธารณะ
{ประกาศสาธารณะ}
จบ;
การดำเนินการ
{$ r *.dfm}
จบ.
มารับข่าวกันเลย "Build With Runtime Packages" ถูกตรวจสอบและตอนนี้พบว่าไฟล์ Runtime ProjectExe.exe มีเพียงสี่ส่วน: สองรูปแบบหนึ่ง sysinit.pas และหนึ่ง projectexe.dpr; ในแผนผังกระบวนการ: RTL60 และ VCL60 เนื้อหาของพวกเขาคือหน่วยที่ปรากฏในการเชื่อมต่อแบบคงที่ในขณะนี้ ProjectExe.exe มีเพียง 16K ในขณะนี้ กล่าวอีกนัยหนึ่งส่วนหนึ่งของหน่วยในกราฟกำกับจะถูกวางไว้ใน EXE และส่วนอื่น ๆ จะถูกวางไว้ใน BPL แต่การแบ่งเป็นอย่างไร? มันขึ้นอยู่กับประโยคการใช้งานหรือขึ้นอยู่กับรายการใน "Build With Runtime Packages" ที่นี่หรือไม่? การทดสอบต่อไปฉันพบว่าหากรายการมีเพียง VCL60 ดังนั้น BPL สองตัวบวกหนึ่ง EXE ที่โหลดลงในหน่วยความจำจะยังคงถูกโหลดลงในหน่วยความจำ EXE มีการเปลี่ยนแปลง: จำนวนหน่วยภายในเพิ่มขึ้นและโดยทั่วไปอยู่ในแพ็คเกจ VCL60 ฉันเดาว่าควรมีความสัมพันธ์ที่ต้องการระหว่างแพ็คเกจ RTL และ VCL สิ่งนี้จะถูกทดสอบในขั้นตอนต่อไป อย่างไรก็ตามในระหว่างกระบวนการประมาณค่าเริ่มต้นรายการแพ็คเกจจะถูกใช้อย่างแน่นอนเพื่อแยกหน่วยที่มีอยู่แล้วในแพ็คเกจจาก EXE
หลังจากการเชื่อมต่อแบบไดนามิกมีปัญหาอื่น: การโหลด มีสองกลยุทธ์สำหรับการโหลดแบบคงที่หรือที่เรียกว่าอัตโนมัติซึ่งสร้างรหัสจาก Delphi และโหลดแพ็คเกจโดยอัตโนมัติก่อนที่จะโหลด EXE; มัน ปัญหาคือฉันต้องคิดออกภายใต้สถานการณ์ใดที่ Delphi จะโหลดแพ็คเกจโดยอัตโนมัติและภายใต้สถานการณ์ใดที่ฉันสามารถหลีกเลี่ยง Delphi ที่ฉลาดเพื่อที่ฉันจะได้ใช้แพ็คเกจได้อย่างยืดหยุ่น ในการทดลองก่อนหน้านี้จะเห็นได้ว่าก่อนที่ไฟล์ DPR จะเริ่มต้นขึ้นแพ็คเกจที่เชื่อมต่อแบบคงที่ได้ถูกโหลดลงในหน่วยความจำ ฉันไม่ทราบกระบวนการเฉพาะ