In my quest to learn C++, I have come across dynamic and static libraries.
I generally get the gist of them: compiled code to include into other programs.
However, I would like to know a few things about them:
- Is writing them any different than a normal C++ program, minus the
main()
function? - How does the compiled program get to be a library? It's obviously not an executable, so how do I turn, say 'test.cpp' into 'test.dll'?
- Once I get it to its format, how do I include it in another program?
- Is there a standard place to put them, so that whatever compilers/linkers need them can find them easily?
- What is the difference (technically and practically) between a dynamic and static library?
- How would I use third party libraries in my code (I'm staring at
.dylib
and.a
files for the MySql C++ Connector)
Everything I have found relating to libraries seems to be targeting those who already know how to use them. I, however, don't. (But would like to!)
Thanks!
(I should also note I'm using Mac OS X, and although would prefer to remain IDE-neutral or command-line oriented, I use QtCreator/Netbeans)
Is writing them any different than a normal C++ program, minus the main() function?
Except for the obvious difference that a library provides services for other programs to use, usually (*) there isn't a difference.
* in gcc classes/functions are exported by default - this isn't the case in VC++, there you have to explicitly export using
__declspec(export)
.How does the compiled program get to be a library? It's obviously not an executable, so how do I turn, say 'test.cpp' into 'test.dll'?
This depends on your compiler. In Visual Studio you specify this in your project configuration. In gcc to create a static library you compile your code normally and then package it in an archive using
ar
. To create a shared you compile first (with the-fpic
flag to enable position independent code generation, a requirement for shared libraries), then use the-shared
flag on the object files. More info can be found in the man pages.Once I get it to its format, how do I include it in another program?
Again this is a little compiler-dependant. In VS, if it's a shared library, when including the class/function you wish to use it should be marked with a
__declspec(import)
(this is usually done with ifdefs) and you have to specify the .lib file of the shared library for linkage. For a static library you only have to specify the .lib file (no export/import needed since the code will end up in your executable).In gcc you only need to specify the library which you link against using
-llibrary_name
.In both cases you will need to provide your client some header files with the functions/classes that are intended for public use.
Is there a standard place to put them, so that whatever compilers/linkers need them can find them easily?
If it's your own library then it's up to you. Usually you can specify the linker additional folders to look in. We have a
lib
folder in our source tree where all.lib
(or .a/.so) files end up and we add that folder to the additional folder to look in.If you're shipping a library on UNIX the common place is usually
/usr/lib
(or/usr/local/lib
), this is also where gcc searches in by default.What is the difference (technically and practically) between a dynamic and static library?
When you link a program to static libraries the code of the libraries ends up in your executable. Practically this makes your executable larger and makes it harder to update/fix a static library for obvious reasons (requires a new version of your executable).
Shared libraries are separate from your executable and are referenced by your program and (usually) loaded at runtime when needed.
It's also possible to load shared libraries without linking to them. It requires more work since you have to manually load the shared library and any symbol you wish to use. On Windows this is done using
LoadLibrary
/GetProcAddress
and on POSIX systems usingdlsym
/dlopen
.How would I use third party libraries in my code?
This is usually accomplished by including the necessary header files and linking with the appropriate library.
A simple example to link with a static library
foo
would look like this:gcc main.cpp -o main.o -L/folder/where/foo.a/is/at -lfoo
.Most open source projects have a readme that gives more detailed instructions, I'd suggest to take a look at it if there is one.
That depends on your definition of "different." From the language's point of view, you write a file or collection of files, don't put in a
main()
and you tell the compiler to generate a library instead of an executable.However, designing libraries is much harder because you have no control over the code that calls you. Libraries need to be more robust against failure than normal code. You can't necessarily
delete
pointers somebody passes to your function. You can't tell what macros will mess with your code. You also can't accidentally pollute the global namespace (eg., don't putusing namespace std
at the beginning of your header files).That depends on the compiler. In Visual C++ this is a project config setting. In gcc (going from memory) it's something like
gcc -c foo.c -shared
.That depends on your compiler and linker. You make sure the header files are available via a project setting or environment variable, and you make sure the binaries are available via a different project setting or compiler variable.
That depends on the operating system. In UNIX you're going to put things in places like
/usr/lib
,/usr/local/lib
. On Windows people used to put DLLs in places likeC:\WINDOWS
but that's no longer allowed. Instead you put it in your program directory.Static libraries are the easier, original model. At compile time the linker puts all the functions from the library into your executable. You can ship the executable without the library, because the library is baked in.
Dynamic libraries (also called shared libraries) involve the compiler putting enough information in the executable that at runtime the linker will be able to find the correct libraries and call the methods in there. The libraries are shared across the whole system among the programs that use them. Using dynamic linking (
dlsym()
, et. al.) adds a few details to the picture.That's going to depend on your platform, and unfortunately I can't tell you much about .dylib files. .a files are static libraries, and you simply need to add them to your final call to gcc (
gcc main.c foo.a -o main
if you know wherefoo.a
is, orgcc main.c -lfoo -o main
if the system knows wherefoo.a
,foo.la
, orfoo.so
are). Generally you make sure the compiler can find the library and leave the linker to do the rest.I'm writing this to be more pragmatic than technically correct. It's enough to give you the general idea of what you're after.
For a static library, there's really not much difference.
For a dynamic library, the most likely difference you'll need to be aware of is that you may need to export the symbols you want to be available outside your library. Basically everything you don't export is invisible to users of your library. Exactly how you export, and whether you even need to by default, depends on your compiler.
For a dynamic library you also need to have all symbols resolved, which means the library can't depend on a function or variable that comes from outside the library. If my library uses a function called foo(), I need to include foo() in my library by writing it myself or by linking to another library that supplies it. I can't use foo() and just assume the user of my library will supply it. The linker won't know how to call a foo() that doesn't yet exist.
It's similar to how you turn test.cpp into test.exe - compile and link. You pass options to the compiler to tell it whether to create an executable, a static library, or a dynamic library.
In your source code, you include header files necessary to use the library, much as you would include a header file for code that's not in a library. You'll also need to include the library on your link line, telling the linker where to find the library. For many systems, creating a dynamic library generates two files, the shared library and a link library. It's the link library that you include on the link line.
There is an environment variable that tells the linker where to look for libraries. The name of that variable is different from one system to another. You can also tell the linker about additional places to look.
A static library gets copied into the thing it is linked to. An executable will include a copy of the static library and can be run on another machine without also copying the static library.
A dynamic library stays in a separate file. The executable loads that separate file when it runs. You have to distribute a copy of the dynamic library with your program or it won't run. You can also replace the dynamic library with a new version, and as long as the new library has the same interface it will still run with the old executable. It also may save space if several executables use the same dynamic library. In fact dynamic libraries are often called shared libraries.
Same as you would use one you created yourself, as described above.
No.
Pass the
-dynamiclib
flag when you're compiling. (The name of the result is still by defaulta.out
. On Mac OS X you should name your dynamic libraries aslib***.dylib
, and on Linux,lib***.so
(shared objects))First, make a header file so the the other program can
#include
to know what functions can be used in your dylib.Second, link to your dylib. If your dylib is named as
libblah.dylib
, you pass the-lblah
flag to gcc./usr/lib
or/usr/local/lib
.Basically, for a static lib, the whole library is embedded into the file it "links" to.
See the 3rd answer.
The difference between a static and dynamic library is that the linking is done at compile time for static libraries, embedding the executable code into your binary, while for dynamic libraries linking is done dynamically at program start. The advantages are that the libraris can be separately distributed, updated and the code (memory) can be shared among several programs.
To use a library you simply provide -l to g++ for a lib.a or lib.so