windows中使用__declspec(dllexport)来将函数导出类似声明的.def文件,linux中是不需要的,因为它将函数全部导出
参考Linux中创建静态库和动态库
样本代码
test.h
#ifndef __TEST_LIB #define __TEST_LIB void foo(); #endiftest.cpp
#include "test.h" #include <iostream> using namespace std; void foo() { cout<<"hello, i am c++!"<<endl; }main.cpp
#include "test.h" #include <iostream> using namespace std; int main() { foo(); return 0; }编译静态库
g++ -c -o test.o test.cpp ar cr libtest_s.a test.o g++ -o run_s main.cpp -L. -ltest_s
这里可以尝试删除libtest_s.a也是可以执行的
编译动态库
g++ -shared -fPIC -o libtest_d.so test.cpp g++ -o run_d main.cpp -L. -ltest_d需要运行,还需要修改环境变量LD_LIBRARY_PATH, export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH
“PCI”命令行标记告诉GCC产生的代码不要包含对函数和变量具体内存位置的引用,这是因为现在还无法知道使用该消息代码的应用程序会将它连接到哪一段内存地址空间。这样编译出的bill.o可以被用于建立共享链接库。建立共享链接库只需要用GCC的”-shared”标记即可。
如果不加-fPIC,则加载.so文件的代码段时,代码段引用的数据对象需要重定位, 重定位会修改代码段的内容,这就造成每个使用这个.so文件代码段的进程在内核里都会生成这个.so文件代码段的copy.每个copy都不一样,取决于这个.so文件代码段和数据段内存映射的位置,相当于没有使用共享库的优势.
查看函数签名
[root@localhost dylib]# nm ./libtest_s.a|grep foo 0000006c t _GLOBAL__I__Z3foov 00000000 T _Z3foov [root@localhost dylib]# nm ./libtest_d.so|grep foo 000006bc t _GLOBAL__I__Z3foov 00000650 T _Z3foov查看动态库依赖
[root@localhost dylib]# ldd ./run_s linux-gate.so.1 => (0x00b04000) libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x00957000) libm.so.6 => /lib/libm.so.6 (0x002fd000) libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x00814000) libc.so.6 => /lib/libc.so.6 (0x00140000) /lib/ld-linux.so.2 (0x0011a000) [root@localhost dylib]# ldd ./run_d linux-gate.so.1 => (0x00513000) libtest_d.so => ./libtest_d.so (0x0068f000) libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x00957000) libm.so.6 => /lib/libm.so.6 (0x002fd000) libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x00814000) libc.so.6 => /lib/libc.so.6 (0x00140000) /lib/ld-linux.so.2 (0x0011a000)