Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
211 views
in Technique[技术] by (71.8m points)

c++ - Why do we need .lib file in case of importing functions from .dll?

Can you help me to understand, why do we need .lib files when importing functions and data from dll?

I've heard, that it contains a list of the exported functions and data elements from the corresponding dll, but when I used CFF Explorer to explore my dll, I found out that dll already has addresses of exporting functions so I theoretically can link my program with .dll without any additional files.

Can you, please, explain what kind of data is stored in the .lib files more detailed.
And, also, yes, I know, that visual studio forces us to add .lib files into additional dependencies section, but why does it really needs them?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

When your source code statically calls exported DLL functions, or statically accesses exported DLL variables, those references are compiled into your executable's intermediate object files as pointers, whose values get populated at run-time.

When the linker is combining the compiler-generated object files to make the final executable, it has to figure out what all of the compiler-generated references actually refer to. If it can't match a given reference to some piece of code in your executable, it needs to match it to an external DLL instead. So it needs to know which DLLs to even look at, and how those DLLs export things. A DLL may export a given function/variable by name OR by ordinal number, so the linker needs a way to map the identifiers used by your code references to specific entries in the EXPORTS tables of specific .dll files (especially in the case where things are exported by ordinals). Static-link .lib files provide the linker with that mapping information (ie FunctionA maps to Ordinal 123 in DLL XYZ.dll, FunctionB maps to name _FunctionB@4 in DLL ABC.dll, etc).

The linker can then populate the IMPORTS table of your executable with information about the appropriate EXPORTS entries needed, and then make the DLL references in your code point to the correct IMPORTS entries (if the linker can't resolve a compiler-generate reference to a piece of code in your executable, or to a specific DLL export, it aborts with an "unresolved external" error).

Then, when your executable is loaded at run-time, the OS Loader looks at the IMPORTS table to know which DLL exports are needed, so it can then load the appropriate DLLs into memory and update the entries in the IMPORTS table with real memory addresses that are based on each DLL's EXPORTS table (if a referenced DLL fails to load, or if a referenced export fails to be found, the OS Loader aborts loading your executable). That way, when your code calls DLL functions or accesses DLL variables, those accesses go to the right places.

Things are very different if your source code dynamically accesses DLL functions/variables via explicit calls to GetProcAddress() at run-time. In that case, static-link .lib files are not needed for those accesses, since your own code is handling the loading of DLLs into memory and locating the exports that it wants to use.

However, there is a 3rd option that blends the above scenarios together: you can write your code to access the DLL functions/variables statically but use your linker's delay-load feature (if it has one). In that case, you still need static-link .lib files for each delay-loaded DLL you access, but the linker populates a separate DELAYLOAD table in your executable with references to the DLL exports, instead of populating the IMPORTS table. It points the compiler-generated DLL references to stubs in your compiler's RTL that will replace the references with addresses from GetProcAddress() when the stubs are accessed for the first time at run-time, thus avoiding the need for the references to be populated by the OS Loader at load-time. This allows your executable to run normally even if the DLL exports are not present at load-time, and may not even need to load the DLLs at all if they are never used (of course, if your executable does try to access a DLL export dynamically and it fails to load, your code is likely to crash, but that is a separate issue).


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...