การลิงก์ไปยังไฟล์ DLL อาจเกิดขึ้นโดยปริยายในเวลาที่คอมไพล์ลิงก์หรืออย่างชัดเจนในขณะรันไทม์ ไม่ว่าจะด้วยวิธีใด DLL จะโหลดลงในพื้นที่หน่วยความจำประมวลผลและจุดเข้าใช้งานที่ส่งออกทั้งหมดจะพร้อมใช้งานสำหรับแอปพลิเคชัน
หากใช้อย่างชัดเจนในขณะทำงานคุณจะใช้LoadLibrary()
และGetProcAddress()
โหลด DLL ด้วยตนเองและรับตัวชี้ไปยังฟังก์ชันที่คุณต้องการเรียกใช้
หากเชื่อมโยงโดยปริยายเมื่อสร้างโปรแกรมแล้วต้นขั้วสำหรับการส่งออก DLL แต่ละรายการที่ใช้โดยโปรแกรมจะเชื่อมโยงกับโปรแกรมจากไลบรารีนำเข้าและต้นขั้วเหล่านั้นจะได้รับการอัปเดตเมื่อ EXE และ DLL ถูกโหลดเมื่อกระบวนการเริ่มทำงาน (ใช่ฉันง่ายกว่าที่นี่เล็กน้อย ... )
ไม่สมบูรณ์เหล่านั้นต้องมาจากที่ไหนสักแห่งและในห่วงโซ่เครื่องมือของ Microsoft พวกเขามาจากรูปแบบพิเศษของไฟล์ .LIB เรียกว่าห้องสมุดนำเข้า โดยปกติ. LIB ที่จำเป็นจะถูกสร้างขึ้นพร้อมกันกับ DLL และมีต้นขั้วสำหรับแต่ละฟังก์ชันที่ส่งออกจาก DLL
น่าสับสนเวอร์ชันคงที่ของไลบรารีเดียวกันจะถูกจัดส่งเป็นไฟล์. LIB ไม่มีวิธีใดที่จะแยกออกจากกันได้ยกเว้นว่า LIB ที่เป็นไลบรารีนำเข้าสำหรับ DLL มักจะมีขนาดเล็กกว่า (มักจะเล็กกว่ามาก) มากกว่า LIB แบบคงที่ที่ตรงกัน
หากคุณใช้ GCC toolchain โดยบังเอิญคุณไม่จำเป็นต้องนำเข้าไลบรารีเพื่อให้ตรงกับ DLL ของคุณ เวอร์ชันของ Gnu linker ที่พอร์ตไปยัง Windows จะเข้าใจ DLL โดยตรงและสามารถสังเคราะห์ Stubs ที่จำเป็นส่วนใหญ่ได้ทันที
อัปเดต
หากคุณอดไม่ได้ที่จะรู้ว่าน็อตและสลักเกลียวทั้งหมดอยู่ที่ไหนและเกิดอะไรขึ้นจริงๆมีบางอย่างที่ MSDN จะช่วยได้เสมอ บทความของ Matt Pietrek การมองในเชิงลึกในรูปแบบไฟล์ปฏิบัติการแบบพกพา Win32คือภาพรวมที่สมบูรณ์ของรูปแบบของไฟล์ EXE และวิธีการโหลดและเรียกใช้ แม้จะได้รับการอัปเดตให้ครอบคลุม. NET และอื่น ๆ เนื่องจากเดิมเคยปรากฏใน MSDN Magazine ca. พ.ศ. 2545
นอกจากนี้การทราบวิธีเรียนรู้ว่าโปรแกรมใช้ DLLs ใดบ้างจะเป็นประโยชน์ เครื่องมือสำหรับสิ่งนั้นคือ Dependency Walker หรือที่เรียกว่า depend.exe รุ่นของมันจะรวมกับ Visual Studio แต่รุ่นล่าสุดสามารถใช้ได้จากผู้เขียนที่http://www.dependencywalker.com/ สามารถระบุ DLL ทั้งหมดที่ระบุในเวลาลิงก์ (ทั้งการโหลดก่อนกำหนดและการโหลดล่าช้า) และยังสามารถเรียกใช้โปรแกรมและดู DLL เพิ่มเติมใด ๆ ที่โหลดในขณะรันไทม์
อัปเดต 2
ฉันได้เปลี่ยนข้อความก่อนหน้านี้บางส่วนเพื่อชี้แจงในการอ่านซ้ำและใช้เงื่อนไขของการเชื่อมโยงโดยนัยและชัดเจนเพื่อความสอดคล้องกับ MSDN
ดังนั้นเราจึงมีสามวิธีในการทำให้ฟังก์ชันไลบรารีสามารถใช้งานได้โดยโปรแกรม คำถามติดตามผลที่ชัดเจนคือ "ฉันจะเลือกทางไหนได้อย่างไร"
การลิงก์แบบคงที่คือการเชื่อมโยงโปรแกรมจำนวนมาก ไฟล์อ็อบเจ็กต์ทั้งหมดของคุณจะแสดงรายการและรวบรวมไว้ในไฟล์ EXE โดยผู้เชื่อมโยง ระหว่างทางผู้เชื่อมโยงจะดูแลงานเล็ก ๆ น้อย ๆ เช่นการแก้ไขการอ้างอิงถึงสัญลักษณ์ทั่วโลกเพื่อให้โมดูลของคุณสามารถเรียกฟังก์ชันของกันและกันได้ ไลบรารียังสามารถเชื่อมโยงแบบคงที่ ไฟล์อ็อบเจ็กต์ที่ประกอบเป็นไลบรารีจะถูกรวบรวมโดยบรรณารักษ์ในไฟล์. LIB ซึ่งตัวเชื่อมโยงจะค้นหาโมดูลที่มีสัญลักษณ์ที่จำเป็น ผลกระทบอย่างหนึ่งของการลิงก์แบบคงที่คือเฉพาะโมดูลเหล่านั้นจากไลบรารีที่ใช้โดยโปรแกรมเท่านั้นที่เชื่อมโยงกับมัน โมดูลอื่น ๆ จะถูกละเว้น ตัวอย่างเช่นไลบรารีคณิตศาสตร์ C แบบดั้งเดิมมีฟังก์ชันตรีโกณมิติมากมาย แต่ถ้าคุณเชื่อมโยงกับมันและใช้cos()
คุณจะไม่ได้รับสำเนาของรหัสsin()
หรือtan()
เว้นแต่คุณจะเรียกฟังก์ชันเหล่านั้นด้วย สำหรับไลบรารีขนาดใหญ่ที่มีคุณสมบัติมากมายการรวมโมดูลที่เลือกไว้นี้มีความสำคัญ ในหลายแพลตฟอร์มเช่นระบบฝังตัวขนาดทั้งหมดของโค้ดที่พร้อมใช้งานในไลบรารีอาจมีขนาดใหญ่เมื่อเทียบกับพื้นที่ที่มีให้จัดเก็บไฟล์ปฏิบัติการในอุปกรณ์ การจัดการรายละเอียดของการสร้างโปรแกรมสำหรับแพลตฟอร์มเหล่านั้นจะทำได้ยากขึ้น
อย่างไรก็ตามการมีสำเนาของไลบรารีเดียวกันในทุกโปรแกรมที่ทำงานอยู่จะสร้างภาระให้กับระบบที่โดยปกติจะเรียกใช้กระบวนการจำนวนมาก ด้วยระบบหน่วยความจำเสมือนที่เหมาะสมเพจของหน่วยความจำที่มีเนื้อหาเหมือนกันจำเป็นต้องมีอยู่เพียงครั้งเดียวในระบบ แต่สามารถใช้ได้กับหลายกระบวนการ สิ่งนี้สร้างประโยชน์ในการเพิ่มโอกาสที่หน้าที่มีโค้ดมีแนวโน้มที่จะเหมือนกันกับบางเพจในกระบวนการทำงานอื่น ๆ ให้ได้มากที่สุด แต่ถ้าโปรแกรมเชื่อมโยงกับไลบรารีรันไทม์แบบคงที่แต่ละโปรแกรมจะมีการผสมผสานของฟังก์ชันที่แตกต่างกันซึ่งแต่ละฟังก์ชันจัดวางไว้ในการประมวลผลแมปหน่วยความจำในตำแหน่งที่แตกต่างกันและไม่มีโค้ดเพจที่สามารถแชร์ได้มากนักเว้นแต่จะเป็นโปรแกรมที่ทำเองทั้งหมด ทำงานในกระบวนการมากกว่า ดังนั้นแนวคิดเกี่ยวกับ DLL จึงได้รับประโยชน์ที่สำคัญอีกประการหนึ่ง
DLL สำหรับไลบรารีมีฟังก์ชันทั้งหมดพร้อมสำหรับการใช้งานโดยโปรแกรมไคลเอ็นต์ใด ๆ หากหลายโปรแกรมโหลด DLL นั้นก็สามารถแชร์โค้ดเพจได้ทั้งหมด ทุกคนชนะ (ดีจนกว่าคุณจะอัปเดต DLL ด้วยเวอร์ชันใหม่ แต่นั่นไม่ได้เป็นส่วนหนึ่งของเรื่องนี้ Google DLL นรกสำหรับด้านนั้น)
ดังนั้นทางเลือกแรกที่ยิ่งใหญ่ในการวางแผนโครงการใหม่คือระหว่างการเชื่อมโยงแบบไดนามิกและแบบคงที่ ด้วยการเชื่อมโยงแบบคงที่คุณมีไฟล์ที่จะติดตั้งน้อยลงและคุณไม่ได้รับการยกเว้นจากบุคคลภายนอกที่อัปเดต DLL ที่คุณใช้ อย่างไรก็ตามโปรแกรมของคุณมีขนาดใหญ่กว่าและไม่ใช่พลเมืองที่ดีของระบบนิเวศของ Windows ด้วยการเชื่อมโยงแบบไดนามิกคุณมีไฟล์ที่ต้องติดตั้งมากขึ้นคุณอาจมีปัญหากับบุคคลที่สามที่อัปเดต DLL ที่คุณใช้ แต่โดยทั่วไปแล้วคุณจะเป็นมิตรกับกระบวนการอื่น ๆ ในระบบ
ข้อได้เปรียบอย่างมากของ DLL คือสามารถโหลดและใช้งานได้โดยไม่ต้องคอมไพล์ใหม่หรือเชื่อมโยงโปรแกรมหลักอีกครั้ง ซึ่งสามารถอนุญาตให้ผู้ให้บริการไลบรารีบุคคลที่สาม (เช่น Microsoft และ C runtime เป็นต้น) แก้ไขข้อบกพร่องในไลบรารีและแจกจ่าย เมื่อผู้ใช้ติดตั้ง DLL ที่อัปเดตแล้วพวกเขาจะได้รับประโยชน์จากการแก้ไขข้อบกพร่องนั้นทันทีในทุกโปรแกรมที่ใช้ DLL นั้น (เว้นเสียแต่ว่าจะทำให้สิ่งของแตกดู DLL Hell)
ข้อได้เปรียบอื่น ๆ มาจากความแตกต่างระหว่างการโหลดโดยนัยและแบบชัดแจ้ง หากคุณใช้ความพยายามมากขึ้นในการโหลดอย่างชัดเจน DLL อาจไม่มีอยู่ในขณะที่เขียนและเผยแพร่โปรแกรม สิ่งนี้ช่วยให้กลไกส่วนขยายที่สามารถค้นหาและโหลดปลั๊กอินได้เช่น
lib /list xxx.lib
และlink /dump /linkermember xxx.lib
. ดูคำถาม Stack Overflowนี้