Saya tahu ini mungkin tampak cukup mendasar bagi para geek. Tapi saya ingin membuatnya sangat jelas.
Ketika saya ingin menggunakan Win32 DLL, biasanya saya hanya memanggil API seperti LoadLibrary () dan GetProcAdderss (). Tetapi baru-baru ini, saya mengembangkan dengan DirectX9, dan saya perlu menambahkan file d3d9.lib , d3dx9.lib , dll.
Saya sudah cukup mendengar bahwa LIB untuk tautan statis dan DLL untuk tautan dinamis.
Jadi pemahaman saya saat ini adalah bahwa LIB berisi implementasi metode dan terhubung secara statis pada waktu tautan sebagai bagian dari file EXE akhir. Sementara DLL dinamis dimuat saat runtime dan bukan merupakan bagian dari file EXE akhir.
Tetapi terkadang, ada beberapa file LIB yang disertakan dengan file DLL, jadi:
- Untuk apa file LIB ini?
- Bagaimana mereka mencapai tujuan mereka?
- Apakah ada alat yang memungkinkan saya memeriksa bagian dalam file LIB ini?
Perbarui 1
Setelah memeriksa wikipedia, saya ingat bahwa file LIB ini disebut pustaka impor . Tapi saya bertanya-tanya bagaimana cara kerjanya dengan aplikasi utama saya dan DLL yang akan dimuat secara dinamis.
Perbarui 2
Seperti yang dikatakan RBerteig, ada beberapa kode rintisan di file LIB yang lahir dengan DLL. Jadi urutan pemanggilannya harus seperti ini:
Aplikasi utama saya -> rintisan di LIB -> DLL target nyata
Jadi informasi apa yang harus dimuat dalam LIB ini? Saya bisa memikirkan yang berikut:
- File LIB harus berisi jalur lengkap dari DLL yang sesuai; Jadi DLL dapat dimuat oleh runtime.
- Alamat relatif (atau file offset?) Dari setiap titik masuk metode ekspor DLL harus dikodekan dalam stub; Jadi lompatan / panggilan metode yang benar dapat dilakukan.
Apakah saya benar dalam hal ini? Apakah ada yang lebih dari itu?
BTW: Apakah ada alat yang dapat memeriksa perpustakaan impor? Jika saya bisa melihatnya, tidak akan ada keraguan lagi.
sumber
lib /list xxx.lib
danlink /dump /linkermember xxx.lib
. Lihat pertanyaan Stack Overflow ini .dumpbin -headers xxx.lib
berikan beberapa informasi yang lebih rinci, dibandingkan dengan utilitaslib
danlink
.Jawaban:
Menautkan ke file DLL dapat terjadi secara implisit pada waktu
kompilasitautan, atau secara eksplisit pada waktu proses. Either way, DLL akhirnya dimuat ke dalam ruang memori proses, dan semua titik masuk yang diekspor tersedia untuk aplikasi.Jika digunakan secara eksplisit pada waktu proses, Anda menggunakan
LoadLibrary()
danGetProcAddress()
memuat DLL secara manual dan mendapatkan petunjuk ke fungsi yang perlu Anda panggil.Jika ditautkan secara implisit saat program dibuat, maka stub untuk setiap ekspor DLL yang digunakan oleh program akan ditautkan ke program dari pustaka impor, dan stub tersebut diperbarui saat EXE dan DLL dimuat saat proses diluncurkan. (Ya, saya telah menyederhanakan lebih dari sedikit di sini ...)
Rintisan tersebut harus berasal dari suatu tempat, dan dalam rantai alat Microsoft mereka berasal dari bentuk khusus file .LIB yang disebut pustaka impor . .LIB yang diperlukan biasanya dibangun pada waktu yang sama dengan DLL, dan berisi rintisan untuk setiap fungsi yang diekspor dari DLL.
Yang membingungkan, versi statis dari pustaka yang sama juga akan dikirim sebagai file .LIB. Tidak ada cara sepele untuk membedakannya, kecuali bahwa LIB yang merupakan pustaka impor untuk DLL biasanya akan lebih kecil (seringkali jauh lebih kecil) daripada LIB statis yang cocok.
Jika Anda menggunakan toolchain GCC, secara kebetulan, Anda sebenarnya tidak memerlukan pustaka impor untuk mencocokkan DLL Anda. Versi linker Gnu yang di-porting ke Windows memahami DLL secara langsung, dan dapat mensintesis hampir semua stub yang diperlukan dengan cepat.
Memperbarui
Jika Anda tidak dapat menahan diri untuk tidak mengetahui di mana semua mur dan baut sebenarnya dan apa yang sebenarnya terjadi, selalu ada sesuatu di MSDN untuk membantu. Artikel Matt Pietrek, Pandangan Mendalam tentang Format File Eksekusi Portabel Win32 adalah gambaran umum yang sangat lengkap tentang format file EXE dan bagaimana itu dimuat dan dijalankan. Bahkan telah diperbarui untuk mencakup .NET dan lebih banyak lagi sejak pertama kali muncul di Majalah MSDN ca. 2002.
Selain itu, akan sangat membantu untuk mengetahui cara mempelajari dengan tepat DLL apa yang digunakan oleh suatu program. Alat untuk itu adalah Dependency Walker, alias depend.exe. Versi itu disertakan dengan Visual Studio, tetapi versi terbaru tersedia dari pembuatnya di http://www.dependencywalker.com/ . Ini dapat mengidentifikasi semua DLL yang ditentukan pada waktu tautan (baik pemuatan awal dan pemuatan tunda) dan juga dapat menjalankan program dan mengawasi setiap DLL tambahan yang dimuat pada waktu berjalan.
Perbarui 2
Saya telah mengubah beberapa teks sebelumnya untuk memperjelasnya saat membaca ulang, dan menggunakan istilah seni yang secara implisit dan eksplisit menghubungkan untuk konsistensi dengan MSDN.
Jadi, kami memiliki tiga cara agar fungsi perpustakaan dapat tersedia untuk digunakan oleh program. Pertanyaan selanjutnya yang jelas adalah: "Bagaimana saya memilih cara yang mana?"
Penautan statis adalah cara menghubungkan sebagian besar program itu sendiri. Semua file objek Anda terdaftar, dan dikumpulkan bersama ke file EXE oleh linker. Sepanjang jalan, linker menangani tugas-tugas kecil seperti memperbaiki referensi ke simbol global sehingga modul Anda dapat memanggil fungsi satu sama lain. Perpustakaan juga dapat ditautkan secara statis. File objek yang membentuk pustaka dikumpulkan bersama oleh pustakawan dalam file .LIB yang dicari linker untuk modul yang berisi simbol yang diperlukan. Salah satu efek dari tautan statis adalah bahwa hanya modul-modul dari perpustakaan yang digunakan oleh program yang ditautkan ke sana; modul lain diabaikan. Misalnya, pustaka matematika C tradisional mencakup banyak fungsi trigonometri. Tetapi jika Anda menautkannya dan menggunakan
cos()
, Anda tidak akan mendapatkan salinan kode untuksin()
atautan()
kecuali Anda juga memanggil fungsi itu. Untuk perpustakaan besar dengan sekumpulan fitur yang kaya, penyertaan modul secara selektif ini penting. Pada banyak platform seperti sistem tertanam, ukuran total kode yang tersedia untuk digunakan di perpustakaan bisa lebih besar dibandingkan dengan ruang yang tersedia untuk menyimpan file yang dapat dieksekusi di perangkat. Tanpa inklusi selektif, akan lebih sulit untuk mengelola detail program pembangunan untuk platform tersebut.Namun, memiliki salinan pustaka yang sama di setiap program yang berjalan menciptakan beban pada sistem yang biasanya menjalankan banyak proses. Dengan jenis sistem memori virtual yang tepat, halaman memori yang memiliki konten identik hanya perlu ada sekali di sistem, tetapi dapat digunakan oleh banyak proses. Hal ini memberikan manfaat untuk meningkatkan peluang bahwa halaman yang berisi kode cenderung identik dengan beberapa halaman dalam sebanyak mungkin proses yang berjalan. Namun, jika program secara statis menautkan ke pustaka runtime, maka masing-masing memiliki campuran fungsi yang berbeda yang masing-masing diatur dalam memproses peta memori di lokasi yang berbeda, dan tidak banyak halaman kode yang dapat dibagikan kecuali jika program itu sendiri adalah program yang berdiri sendiri. berjalan lebih dari sekedar proses. Jadi gagasan tentang DLL memperoleh keuntungan besar lainnya.
DLL untuk pustaka berisi semua fungsinya, siap digunakan oleh program klien apa pun. Jika banyak program memuat DLL itu, mereka semua dapat berbagi halaman kodenya. Semua orang menang. (Nah, sampai Anda memperbarui DLL dengan versi baru, tapi itu bukan bagian dari cerita ini. Google DLL Neraka untuk sisi kisah itu.)
Jadi, pilihan besar pertama yang harus diambil ketika merencanakan proyek baru adalah antara hubungan dinamis dan statis. Dengan tautan statis, Anda memiliki lebih sedikit file untuk diinstal, dan Anda kebal dari pihak ketiga yang memperbarui DLL yang Anda gunakan. Namun, program Anda lebih besar, dan itu tidak cukup baik untuk ekosistem Windows. Dengan tautan dinamis, Anda memiliki lebih banyak file untuk diinstal, Anda mungkin memiliki masalah dengan pihak ketiga yang memperbarui DLL yang Anda gunakan, tetapi Anda secara umum lebih ramah terhadap proses lain di sistem.
Keuntungan besar dari DLL adalah ia dapat dimuat dan digunakan tanpa kompilasi ulang atau bahkan menautkan ulang program utama. Ini memungkinkan penyedia pustaka pihak ketiga (misalnya Microsoft dan runtime C) untuk memperbaiki bug di pustaka mereka dan mendistribusikannya. Setelah pengguna akhir menginstal DLL yang diperbarui, mereka segera mendapatkan manfaat dari perbaikan bug tersebut di semua program yang menggunakan DLL tersebut. (Kecuali itu merusak banyak hal. Lihat DLL Hell.)
Keuntungan lainnya berasal dari perbedaan antara pemuatan implisit dan eksplisit. Jika Anda melakukan upaya ekstra untuk memuat eksplisit, DLL mungkin bahkan tidak ada saat program ditulis dan diterbitkan. Ini memungkinkan mekanisme ekstensi yang dapat menemukan dan memuat plugin, misalnya.
sumber
File pustaka impor .LIB ini digunakan dalam properti proyek berikut
Linker->Input->Additional Dependencies
, ketika membuat sekumpulan dll yang membutuhkan informasi tambahan pada waktu tautan yang disediakan oleh pustaka impor. File .LIB. Dalam contoh di bawah ini untuk tidak mendapatkan kesalahan linker saya perlu merujuk ke dll A, B, C, dan D melalui file lib mereka. (perhatikan agar linker menemukan file ini, Anda mungkin perlu menyertakan jalur penerapannya,Linker->General->Additional Library Directories
jika tidak, Anda akan mendapatkan error build karena tidak dapat menemukan file lib yang disediakan.)Jika solusi Anda membangun semua pustaka dinamis, Anda mungkin dapat menghindari spesifikasi ketergantungan eksplisit ini dengan mengandalkan bendera referensi yang ditampilkan di bawah
Common Properties->Framework and References
dialog. Bendera ini tampaknya secara otomatis melakukan penautan atas nama Anda menggunakan file * .lib.Namun ini seperti yang dikatakan Properti Umum , yang tidak spesifik konfigurasi atau platform. Jika Anda perlu mendukung skenario build campuran seperti dalam aplikasi kami, kami memiliki konfigurasi build untuk merender build statis dan konfigurasi khusus yang membangun build terbatas dari subset rakitan yang diterapkan sebagai library dinamis. Saya telah menggunakan
Use Library Dependency Inputs
andLink Library Dependencies
flags yang disetel ke true dalam berbagai kasus untuk mendapatkan sesuatu untuk dibangun dan kemudian disadari untuk menyederhanakan hal-hal tetapi ketika memperkenalkan kode saya ke build statis, saya memperkenalkan banyak peringatan linker dan build itu sangat lambat untuk build statis. Saya akhirnya memperkenalkan banyak peringatan semacam ini ...warning LNK4006: "bool __cdecl XXX::YYY() already defined in CoreLibrary.lib(JSource.obj); second definition ignored D.lib(JSource.obj)
Dan saya akhirnya menggunakan spesifikasi manual
Additional Dependencies
untuk memenuhi linker untuk build dinamis sambil menjaga agar pembuat statis senang dengan tidak menggunakan properti umum yang memperlambatnya. Ketika saya menyebarkan subset dinamis membangun saya hanya menyebarkan file dll karena file lib ini hanya digunakan pada waktu link, bukan saat runtime.sumber
Ada tiga jenis pustaka: pustaka statis, bersama dan dimuat secara dinamis.
Pustaka statis ditautkan dengan kode pada fase penautan, jadi sebenarnya pustaka tersebut dapat dieksekusi, tidak seperti pustaka bersama, yang hanya memiliki stub (simbol) untuk dicari di file pustaka bersama, yang dimuat pada waktu proses sebelum fungsi utama dipanggil.
Yang dimuat secara dinamis sangat mirip dengan pustaka bersama, kecuali mereka dimuat ketika dan jika perlu muncul oleh kode yang Anda tulis.
sumber
LoadLibrary()
dan API terkait.Berikut beberapa topik MSDN terkait untuk menjawab pertanyaan saya:
Menautkan Executable ke DLL
Menghubungkan secara implisit
Menentukan Metode Penautan Yang Akan Digunakan
Membangun Perpustakaan Impor dan Ekspor File
sumber