linux library
1 #include <iostream> 2 #include <mylib.h> 3 using namespace std; 4 int main() 5 { 6 while(1) 7 { 8 cout_t(5); 9 } 10 return 0; 11 12 }
#ifndef MYLIB_H_ #define MYLIB_H_ extern "C" void cout_t(int x); #endif
#include <iostream> #include "mylib.h" using namespace std; void cout_t(int x) { int y = x + 10; cout<<"resut is :"<<y<<endl; }
编译过程
//-fPIC Position-Independent Code
gcc -c -Wall -fPIC mylib.cpp //单独编译动态库于其他路径(和main不再同一文件夹内)要加-c
gcc -Wall -shared -o libmylib.so mylib.o // 有链接过程
nm -D ./libmylib.so
gcc -Wall -I/mnt/Working/DEVELOPMENT/C++/Linux_lib_study/lib -L/mnt/Working/DEVELOPMENT/C++/Linux_lib_study/lib -lmylib -o main main.cpp -lstdc++ //编译main 链接mylib
如果出现:
undefined reference to `std::ios_base::Init::Init()'
或者
error while loading shared libraries: libmylib.so: cannot open shared object file: No such file or d
则:
export LD_LIBRARY_PATH=/mnt/Working/DEVELOPMENT/C++/Linux_lib_study/lib
GCC采用搜索目录的办法来查找所需要的文件,-I选项可以向GCC的头文件搜索路径中添加新的目录。比如把mylib.h和mylib.cpp单独放一个lib文件夹。
为了让GCC能够顺利地找到它们(头文件),
-I /mnt/Working/DEVELOPMENT/C++/Linux_lib_study/lib
同样,如果使用了不在标准位置的库文件,那么可以通过-L选项向GCC的库文件搜索路径中添加新的目录,为了让GCC能够顺利地找到它( 库文件),
-L/mnt/Working/DEVELOPMENT/C++/Linux_lib_study/lib
然而使用CMake
project(TEST)
set(MYLIB_DIR "/mnt/Working/DEVELOPMENT/C++/Linux_lib_study/lib")
add_library(mylib SHARED ${MYLIB_DIR}/mylib.cpp)
ADD_EXECUTABLE(main main.cpp)
link_directories({CMAKE_BINARY_DIR}/)
TARGET_LINK_LIBRARIES(main ${MYLIB_DIR}/mylib)
一撸到底
一:静态库
1.ar
ar命令可以用来创建、修改库,也可以从库中提出单个模块。库是一单独的文件,里面包含了按照特定的结构组织起来的其它的一些文件(称做此库文件的member)。原始文件的内容、模式、时间戳、属主、组等属性都保留在库文件中。
ar [-]{dmpqrtx}[abcfilNoPsSuvV] [membername] [count] archive files...
ar rv libtest.a hello.o hello1.o
生成一个库,库名字是test,链接时可以用-ltest链接。该库中存放了两个模块hello.o和hello1.o。选项前可以有‘-'字符。
二.共享库
第一个程序调用的时候,库的副本会被加载到内存中,所以会花费相对较长的时间,其他程序调用统一个库的时候只是复制库的副本(每个程序都会有自己的全局和静态变量)。
每个程序都有自己的副本,所以数据不会混乱,但是如果一个程序的不同进程或者线程调用呢?会不会使数据串了?
-fPIC 制定编译器应该生成位置独立的代码,这会改变编译器生成执行特定操作的代码的方式,包括访问全局变量、静态和外部变量。访问字符串常量以及获取函数地址。这些变更使得代码可以再运行是被放置再任意一个虚拟地址处。
用以下命令来检查是否使用了 -fPIC:
[alpha@alpha lib]$ nm mylib.o | grep _GLOBAL_OFFSET_TABLE_
U _GLOBAL_OFFSET_TABLE_
[alpha@alpha lib]$ readelf -s mylib.o | grep _GLOBAL_OFFSET_TABLE_
14: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND _GLOBAL_OFFSET_TABLE_
下面两个命令有输出,就表示有模块没使用-fPIC
[alpha@alpha lib]$ objdump --all-headers libmylib.so | grep TEXTEL
[alpha@alpha lib]$ readelf -d libmylib.so | grep TEXTREL