C Programming 101
Assignment 2: Create a library and use (static and dynamic)
There is a lot of content online to understand static and dynamic linking of code. I am documenting quick steps to use both in your code.
Static Linking
Your header files declare all your exported function prototypes.
library.h
#ifndef _LIBRARY_H_ #define _LIBRARY_H_ void SayHello(void); #endif
Your “c” files implements the functions declared in .h file
library.c
#include "library.h" #include void SayHello() { printf("Hello, World!\n"); }
Compile your library code
cl /LD library.c
...
/out:library.dll
/dll
/implib:library.lib
library.obj
09/07/2018 10:17 PM 93 hello.c
09/08/2018 08:50 AM 101 library.c
09/08/2018 10:29 AM 125,952 library.dll
09/08/2018 10:28 AM 122 library.h
09/08/2018 10:29 AM 2,356 library.obj
Write code to consume SayHello function.
/* * Hello.c */ #include "library.h" int main() { SayHello(); return 0; }
All this program knows is that library.h declares a function with prototype “void SayHello()”, exists somewhere. If you build hello.c, it will build obj file but there will be a linker error failing to resolve SayHello().
cl hello.c
...
/out:hello.exe
hello.obj
hello.obj : error LNK2019: unresolved external symbol SayHello referenced in function main
hello.exe : fatal error LNK1120: 1 unresolved externals
You need to tell compiler where to find implementation of SayHello(); it is in library.obj
cl hello.c library.obj ... /out:hello.exe hello.obj library.obj 130,048 hello.exe > hello.exe Hello, World!
The size of exe is 127KB, code for SayHello is now embedded within the exe.
Dynamic Linking
To dynamically link your SayHello code, you need to make a minor modification to your header file. Add a __declspec attribute to specify storage class for the declared function.
#ifndef _LIBRARY_H_ #define _LIBRARY_H_ __declspec(dllexport) void SayHello(void); #endif
Now when you compile this code, you get a dll, an obj and a lib file.
cl /LD library.c ... /out:library.dll /dll /implib:library.lib library.obj Creating library library.lib and object library.exp 09/07/2018 10:17 PM 93 hello.c 09/08/2018 08:50 AM 101 library.c 09/08/2018 10:42 AM 125,952 library.dll 09/08/2018 10:42 AM 658 library.exp 09/08/2018 10:39 AM 98 library.h 09/08/2018 10:42 AM 1,702 library.lib 09/08/2018 10:42 AM 2,373 library.obj
To dynamically link to your library code, you don’t link with the obj, you need to link with the lib file.
cl hello.c library.lib ... /out:hello.exe hello.obj library.lib 105,984 hello.exe >hello.exe Hello, World!
Notice, the size of exe is 104KB, considerably smaller than the statically linked binary. SayHello is dynamically resolved by the Loader when your program runs. If it is unable to find the dll, program will terminate. So, you need to ensure that the dll is distributed with your program code.
So how does Loader get to know which dll has your function?
The information is embedded in the executable headers. We can dump the import table to find this out.
link /dump /imports hello.exe
Microsoft (R) COFF/PE Dumper Version 14.15.26726.0
Copyright (C) Microsoft Corporation. All rights reserved.
Dump of file hello.exe
File Type: EXECUTABLE IMAGE
Section contains the following imports:
library.dll
140010230 Import Address Table
140018A58 Import Name Table
0 time date stamp
0 Index of first forwarder reference
0 SayHello
...
If you look in the dll’s export table, this function is exported from the dll.
link /dump /exports library.dll
Microsoft (R) COFF/PE Dumper Version 14.15.26726.0
Copyright (C) Microsoft Corporation. All rights reserved.
Dump of file library.dll
File Type: DLL
Section contains the following exports for library.dll
00000000 characteristics
FFFFFFFF time date stamp
0.00 version
1 ordinal base
1 number of functions
1 number of names
ordinal hint RVA name
1 0 00001000 SayHello
Summary
2000 .data
2000 .pdata
A000 .rdata
1000 .reloc
13000 .text
There is only one function exported by our dll. You can add more!