On Linux or other UNIX systems, build the .o file with:g++ foo.cpp -c -fPIC The "-fPIC" is for "Position Independent Code", and it sets up the "Global Offset Table" stuff described below in "The Horror of UNIX Shared Libraries". |
On Windows, build the .obj files with:cl /TP /GR /EHsc /MD /c foo.cpp The "/MD" links your code with the multithreaded C standard library; if you forget this, you'll get a bizarre inexplicable crash inside "fseek" in your library. You'll also have to add DLL export and import statements to your header as described below in the "The Horror of Windows DLLs". |
On Linux, build the .so file with:g++ -shared foo.o -o foo.soOn Mac OS X, build the .so file with: g++ -dynamiclib foo.o -o foo.soI highly recommend also using the hideous flag "-Wl,-rpath=." to make Linux look in the current directory for shared libraries. |
On Windows, build the .dll and .lib files with:cl /LD /link /TP /GR /EHsc /MD foo.obj -ofoo.dll"/LD" means make a shared library. |
On UNIX-like systems:g++ main.cpp foo.so -o mainThe resulting executable will look for "foo.so" when run. "foo.so" must either be copied to one of the system /lib directories, or you need to "export LD_LIBRARY_PATH=.", or you need to use rpath when compiling "foo.so". UNIX is pretty silly about refusing to admit that foo.so is sitting right next to the executable that needs it. |
On Windows:cl /TP /GR /EHsc /MD main.cpp foo.lib -omain.exeNote that you link with the ".lib" file, but at runtime main.exe will require "foo.dll". The DLL can be in the same directory as main, or in C:\Windows\System32, and it will just work. You can also put a line like this into main.cpp (or foo.h!), and then you don't even need to list foo.lib on the command line or in the IDE: #pragma comment (lib,"foo.lib") |
int thingy;(executable NetRun link)
int foo(void) {
return thingy+5;
}
00000000 <foo>:The GOT is hence:
Standard compiler-generated "function prologue" to set up the stack frame:
0: 55 push ebp
1: 89 e5 mov ebp,esp
This weirdness just loads up the program counter (address of this code) into ecx:
3: e8 00 00 00 00 call 8 <foo+0x8>
8: 59 pop ecx
The GOT is attached at link time to this code; so it's at a fixed offset from here:
9: 81 c1 03 00 00 00 add ecx,0x3
b: R_386_GOTPC _GLOBAL_OFFSET_TABLE_
The current address of each global is stored in the GOT--each function and global has a slot:
f: 8b 81 00 00 00 00 mov eax,DWORD PTR [ecx]
11: R_386_GOT32 thingy
Finally, we've loaded up eax with the address of "thingy", so we can start using it:
15: 8b 00 mov eax,DWORD PTR [eax]
17: 83 c0 05 add eax,0x5
1a: 5d pop ebp
1b: c3 ret