__declspec (dllimport) หมายความว่าอย่างไร


92

ฉันเห็นซอร์สโค้ด Qt ดังนี้:

class Q_CORE_EXPORT QBasicAtomicInt
{
public:
...
};

Q_CORE_EXPORTมาโครใดที่กำหนดไว้ด้านล่าง:

define Q_DECL_IMPORT __declspec(dllimport)

แล้วมัน__declspec(dllimport)หมายความว่าอย่างไร?


คำตอบ:


118

__declspecเป็นแอตทริบิวต์เฉพาะของ Microsoft ที่อนุญาตให้คุณระบุข้อมูลระดับพื้นที่เก็บข้อมูล
(มุมของ Nitpicker: อย่างไรก็ตามผู้จำหน่ายคอมไพเลอร์อื่น ๆ อีกจำนวนหนึ่งเช่น GCC สนับสนุนส่วนขยายภาษานี้เพื่อความเข้ากันได้กับฐานรหัสที่ติดตั้งซึ่งเขียนขึ้นโดยกำหนดเป้าหมายเป็นคอมไพเลอร์ของ Microsoft บางรายยังมีแอตทริบิวต์ระดับพื้นที่จัดเก็บเพิ่มเติม)

สองของผู้ที่แอตทริบิวต์การจัดเก็บข้อมูลระดับที่สามารถระบุและdllimport dllexportสิ่งเหล่านี้ระบุให้คอมไพเลอร์ทราบว่าฟังก์ชันหรืออ็อบเจ็กต์ถูกอิมพอร์ตหรือเอ็กซ์พอร์ต (ตามลำดับ) จาก DLL

โดยเฉพาะอย่างยิ่งพวกเขากำหนดอินเทอร์เฟซของ DLL ให้กับไคลเอนต์โดยไม่ต้องใช้ไฟล์ module-definition ( .DEF) คนส่วนใหญ่พบว่าการใช้นามสกุลภาษาเหล่านี้ง่ายกว่าการสร้างไฟล์ DEF

ด้วยเหตุผลที่ชัดเจน__declspec(dllimport)และ__declspec(dllexport)โดยทั่วไปมักจับคู่กัน คุณใช้dllexportเพื่อทำเครื่องหมายสัญลักษณ์ว่าส่งออกจาก DLL และคุณใช้dllimportเพื่ออิมพอร์ตสัญลักษณ์ที่เอ็กซ์พอร์ตนั้นในไฟล์อื่น

ด้วยเหตุนี้และเนื่องจากโดยทั่วไปไฟล์ส่วนหัวเดียวกันจึงถูกใช้ทั้งในการคอมไพล์ DLL และในโค้ดไคลเอนต์ที่ใช้อินเทอร์เฟซของ DLL จึงเป็นรูปแบบทั่วไปในการกำหนดมาโครที่จะแก้ไขโดยอัตโนมัติเป็นตัวระบุแอตทริบิวต์ที่เหมาะสมในเวลาคอมไพล์ ตัวอย่างเช่น:

#if COMPILING_DLL
    #define DLLEXPORT __declspec(dllexport)
#else
    #define DLLEXPORT __declspec(dllimport)
#endif

DLLEXPORTและจากนั้นทำเครื่องหมายสัญลักษณ์ทั้งหมดที่ควรจะส่งออกด้วย

สันนิษฐานว่าคือสิ่งที่Q_CORE_EXPORTแมโครไม่แก้ไขปัญหาอย่างใดอย่างหนึ่งหรือQ_DECL_IMPORTQ_DECL_EXPORT


__declspec ไม่ใช่ "เฉพาะ MS" อย่างถูกต้อง ("เฉพาะของคอมไพเลอร์มากกว่ามาก) และคอมไพเลอร์บางตัวก็ใช้การประกาศนี้สำหรับหลายแพลตฟอร์มด้วยเช่นกันค่าแอตทริบิวต์บางค่า ได้แก่ (dllexport / dllimports เป็น MS เฉพาะเนื่องจาก DLL เป็น MS ศัพท์)
Emilio Garavaglia

9
@Emilio: เท่าที่ฉันทราบ Microsoft ได้คิดค้น__declspecสัญกรณ์เพื่อเป็นส่วนขยายของภาษา C ++ ฉันเชื่อว่า GCC รองรับแล้ว แต่ส่วนใหญ่เป็นเพราะเหตุผลด้านความเข้ากันได้กับคอมไพเลอร์ของ Microsoft และฉันไม่เข้าใจว่า "เฉพาะ MS" แตกต่างจาก "คอมไพเลอร์เฉพาะ" อย่างไร Microsoft เขียนคอมไพเลอร์ C ++ และมีผู้คนจำนวนมากใช้งาน มาพร้อมกับ Visual Studio
โคดี้เกรย์

8
Microsoft สร้างคอมไพเลอร์ เรียกว่า "Microsoft C / C ++ Optimizing Compiler", cl.exe ผู้คนจำนวนมากอ้างถึง Visual Studio อย่างผิดพลาดราวกับว่าเป็นคอมไพเลอร์ แต่เป็น IDE ฉันไม่รู้ว่าทำไมผู้คนถึงเลือกไม่ถูกว่า "เฉพาะ Microsoft" หมายถึงอะไร ไม่ได้หมายถึง "สภาพแวดล้อม MS" (ไม่ว่าจะเป็นอะไรก็ตาม) และไม่ได้หมายถึง "Windows" อย่างแน่นอน ใช่ขณะนี้ผู้จำหน่ายคอมไพเลอร์รายอื่นสนับสนุนส่วนขยายสำหรับความเข้ากันได้กับฐานที่ติดตั้งของโค้ดที่เขียนขึ้นโดยกำหนดเป้าหมายคอมไพเลอร์ Microsoft ดังที่ฉันได้กล่าวไปแล้วเท่าที่ฉันทราบ Microsoft ได้คิดค้นไวยากรณ์ นั่นคือประเด็นที่เกิดขึ้นที่นี่
โคดี้เกรย์

2
@CodyGray: Microsoft ได้คิดค้นมันขึ้นมาเพียงอย่างเดียวคงไม่เพียงพอ อย่างไรก็ตามไมโครซอฟท์ได้คิดค้นมันขึ้นมาโดยไม่มีมาตรฐานใด ๆ ที่มีอยู่ แต่คนอื่น ๆ ใช้เพียงเพื่อความเข้ากันได้และใช้เป็นหลัก (ถ้าไม่ใช่เฉพาะ) สำหรับโปรแกรมที่กำหนดเป้าหมาย Microsoft Windows ด้วยกันทำให้เป็นจุดแข็งมากสำหรับการเรียกมันว่า "เฉพาะ Microsoft"
celtschk

6
นี่เป็นคำตอบที่ยอดเยี่ยมโดยเฉพาะส่วนที่เกี่ยวกับ "เพราะโดยทั่วไปไฟล์ส่วนหัวเดียวกันจะใช้ทั้งในขณะคอมไพล์ DLL และในรหัสไคลเอนต์"! ทำให้ทุกแง่มุมของการนำเข้า / ส่งออกมีความชัดเจน
Ela782

30

__declspec(dllimport) เป็นตัวระบุคลาสหน่วยเก็บข้อมูลที่บอกคอมไพลเลอร์ว่าฟังก์ชันหรืออ็อบเจ็กต์หรือชนิดข้อมูลถูกกำหนดไว้ใน DLL ภายนอก

ฟังก์ชันหรือวัตถุหรือชนิดข้อมูลจะถูกส่งออกจาก DLL ที่มีไฟล์__declspec(dllexport).


6
ตกลง. ในที่สุดหลังจาก 2 ชั่วโมงของการอ่านฉันพบว่าสิ่งที่ฉันต้องการนั้นมีความพึงพอใจกระชับและตรงประเด็นที่สุด
el psy Congroo

1

__declspec(dllexport)บอกให้คอมไพเลอร์แจ้งผู้เชื่อมโยงว่าต้องวางสัญลักษณ์เหล่านี้ในตารางการส่งออก (เมื่อรวบรวม. dll) เมื่อคอมไพล์โปรแกรมที่เชื่อมโยงกับ. dll __declspec(dllimport)บอกคอมไพลเลอร์ให้สร้างการเรียกทางอ้อมที่สัมพันธ์กับการลงทะเบียนแบบสัมบูรณ์(ซึ่งตัวเชื่อมโยงจะกรอกคำแก้ไขเพื่อชี้ไปที่ตารางนำเข้า) แทนที่จะเป็นทะเบียนญาติ rip-relative -directตามปกติคำสั่งการโทรทางอ้อมไปยังฟังก์ชันที่ไม่ได้กำหนด (ซึ่งไม่สามารถแก้ไขคำสั่งได้ตัวเชื่อมโยงจะแทรกที่อยู่สัมพัทธ์ของ thunk จากนั้นสร้าง thunk ซึ่งภายในจะวางการเรียกทางอ้อมที่สัมพันธ์กันโดยสมบูรณ์แบบสัมพันธ์กับ ตัวชี้ฟังก์ชันในตารางการนำเข้า) นี่คือขนาดรหัสและการเพิ่มประสิทธิภาพความเร็ว เป็นไลบรารีอิมพอร์ต. lib ที่บอกผู้เชื่อมโยงว่าจะนำเข้าสัญลักษณ์ใดและใช้เป็นแนวทางในการสร้างตารางการนำเข้าและสร้างสิ่งที่จำเป็นในเซ็กเมนต์. text

https://docs.microsoft.com/en-us/cpp/build/importing-function-calls-using-declspec-dllimport?view=vs-2019 https://docs.microsoft.com/en-us/cpp / build / import-data-using-Declspec-dllimport? view = vs-2019 https://stackoverflow.com/a/4490536/7194773


-2

หมายความว่านิยามของฟังก์ชันอยู่ในไดนามิกไลบรารี โปรดดูเอกสารสำหรับรายละเอียดและตัวอย่างเพิ่มเติม

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.