Question

I am having some trouble understanding why both #include and LoadLibrary() is needed in C++. In C++ "#include" forces the pre-processor to replace the #include line with the contents of the file you are including (usually a header file containing declarations). As far as I understand, this enables me to use the routines I might want in the external libraries the headers belong to.

Why do I then need LoadLibrary()? Can't i just #include the library itself?

Just as a side note: In C#, which I am more familiar with, I just Add a Reference to a DLL if I want to use types or routines from that DLL in my program. I do not have to #include anything, as the .NET framework apparently automatically searches all the referenced assemblies for the routines I want to use (as specified by the namespace)

Thank you very much in advance.

Edit: Used the word "definitions", but meant "declarations". Now fixed.

Edit 2: Tough to pick one answer, many good replies. Thanks for all contributions.

Était-ce utile?

La solution

C++ uses a full separate compilation model; you can even compile against code which hasn't been written. (This often occurs in large projects.) When you include a file, all you are doing is telling the compiler that the functions, etc. exist. You do not provide an implementation (except for inline functions and templates). In order to execute the code, you have to provide the implementation, by linking it into your application. This can occur in several different ways:

  • You have the source files; you compile them along with your sources, and link in the resulting objects.

  • You have a static library; you must link against it.

  • You have a dynamic library. Here, what you must do will depend on the implemention: under Windows, you must link against a .lib stub, and put the .dll somewhere where the runtime will find it when you execute. (Putting it in the same directory as your application is usually a good solution.)

I don't quite understand your need to call LoadLibrary. The only time I've needed this is when I've intentionally avoided using anything in the library directly, and want to load it conditionally, use GetProcAddr to get the addresses of the functions I need.

EDIT:

Since I was asked to clarify "linking": program translation (from the source to an executable) takes place in a number of steps. In traditional terms, each translation unit is "compiled" into an object file, which contains an image of the machine instructions, but with unfilled spaces for external references. For example, if you have:

extern void function();

in your source (probably via inclusion of a header), and you call function, the compiler will leave the address field of the call instruction blank, since it doesn't know where the function will be located. Linking is the process of taking all of the object files, and filling in these blanks. One of the object files will define function, and the linker will establish the actual address in the memory image, and fill in the blank referring to function with the address of function in that image. The result is a complete memory image of the executable. On the early systems I worked on: literally. The OS would simply copy the executable file directly into memory, and then jump into it. Things like virtual memory and shared, write protected code segments make this a little more complicated today, but for statically linked libraries or object files (my first two cases above), the differences aren't that great.

Modern system technologies have blurred the lines somewhat. For example, most Java (and I think C#) compilers don't generate classical object files, with machine code, but rather byte code, and the compile and link phases, above, don't take place until runtime. Some C++ compilers also only generate byte code, which will be compiled when the code is "linked". This is done to permit cross-module optimizations. And all modern systems support dynamic linking: some of the blank addresses are left blank until execution time. And dynamic linking can be implicit or explicit: when it is implicit, the link phase will insert information into the executable concerning the libraries it needs, and where to find them, and the OS will link them, implicitly, either when the executable is loaded, or on demand, triggered by the code attempting to use one of the unfilled address slots. When it is explicit, you normally don't have any explicit referenced to the name in your code. In the case of function, above, for example, you wouldn't have any code which directly called function. Your code would, however, load the dynamic library using LoadLibrary (or dlopen under Unix), then request the address of a name, using GetProcAddr (or dlsys), and call the function indirectly through the pointer it received.

Autres conseils

The #include directive is, like all preprocessor functionality, merely a text replacement. The text "#include " is replaced with the contents of that file.

Typically (but not necessarily), this is used to include a header file which declares the functions that you want to use, i.e. you tell the compiler (which runs after the preprocessor) how some functions that you intend to use are named, what parameters they take, and what the return type is. It does not define what the function is actually doing.

You then also need an implementation of these functions, too. Usually, if you do not implement them in your program, you leave this task to the link stage. You give a list of libraries that your program depends on to the linker, and the linker divines via some implementation-defined way (such as an "import library") what it needs to do to "make it work". The linker will produce some glue code and write some information into the executable that will make the loader automatically load the required libraries. Everything "just works" without you having to do something special.

In some cases, however, you want to postpone the linker stage and do the loading "fully dynamically" by hand rather than automatically. This is when you have to call LoadLibrary() and GetProcAddress. The former brings the DLL into memory and does some setup (e.g. relocation), the latter gives you the address of a function that you want to call. The #include in your code is still necessary so the compiler knows what to do with that pointer. Otherwise, you could of course call the obtained function via its address, but it would not be possible to call the function in a meaningful way.

One reason why one would want to load a library manually (using LoadLibrary) is that it is more failsafe. If you link a program against a library and the library cannot be found (or a symbol cannot be found), then your application will not start up and the user will see a more or less obscure error message.
If LoadLibrary fails or GetProcAddress doesn't work, your program can in principle still run, albeit with reduced functionality.

Another example for using LoadLibrary might be to load an alternative version of a function from a different library (some programs implement "plugins" that way). The function "looks" the same to the compiler, as defined in the include file, but may behave differently, as by whatever is in the loaded binary.

#include brings in source code only: symbol declarations for the compiler. A library (or a DLL) is object code: Use either LoadLibrary or link to a lib file to bring in object code.

LoadLibrary() causes the code module to be loaded from disk into your applications memory space for execution. This allows for dynamically loading code at runtime. You would not use LoadLibrary(), for example, if the code you want to use is compiled into a statically linked library. In that case you would provide the name of the .lib file that contained the code to the linker and it gets resolved at link time - the code is linked in to your .exe and the .lib is not distributed with the .exe in order for it to execute.

LoadLibrary() creates a dependency on an external DLL which must be present on the path provided to the method call in order for the .exe to properly execute. If LoadLibrary() fails, you must ensure your code will handle it appropriately, by either exiting gracefully or providing some other execution alternative. You must provide a .lib file to the linker the same as you would for the static library above. This .lib file however does not contain code, just entry points for the actual code that resides in the .dll.

In both cases you must #include the headers for the code you wish to execute. This is required by the compiler in order to build function call signatures properly based on the type information provided by the header.

C# assemblies contain both type information and IL. A single reference is sufficient to satisfy the need for header information and binding to the code itself.

#include is static, the substitution is done at compile time. LoadLibrary() lets you load a DLL at runtime, for example based on user imput.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top