gcc :GNU编译器套件(GNU Compiler Collection)是到了4.7,才真正支持c11的。
gcc & g++如今是gnu中最主要和最流行的c & c++编译器 。
g++是将默认语言设为c++,连接时自动使用C++标准库而不用c标准库 。
C++标准库:http://www.runoob.com/cplusplus/cpp-standard-library.htmlhtml
调试选项 -g和-pglinux
优化选项 -O(0~3) 优化编译、连接,-O0表示没有优化,-O1为缺省值,-O3优化级别最高;ios
目录选项c++
错误与警告选项多线程
连接方式函数
其余选项工具
在实际开发过程当中,各个模块之间会涉及到一些通用的功能,好比读写文件,查找、排序。为了减小代码的冗余,提升代码的质量,能够将这些通用的部分提取出来,作出公共的模块库。经过动态连接库能够实现多个模块之间共享公共的函数。优化
建立动态库,经过shared和fPIC编译参数生产so动态连接库文件。程序在调用库函数时,只须要链接上这个库便可。spa
/*caculate.h*/ #ifndef CACULATE_HEAD #define CACULATE_HEAD int add(int a, int b); int sub(int a, int b); int div(int a, int b); int mul(int a, int b); #endif /*caculate.c文件*/ #include "caculate.h" extern "C"{ int add(int a, int b) { return (a + b); } int sub(int a, int b) { return (a - b); } int div(int a, int b) { return (int)(a / b); } int mul(int a, int b) { return (a * b); } }
编译生产libcac.so文件以下插件
g++ -fPIC -shared -o libxxx.so xx1.cpp xx2.cpp xx3.cpp //多个文件成成一个动态链接库 g++ -fPIC -shared caculate.cpp -o libcac.so
#include <stdio.h> #include "caculate.h" int main(){ int a = 20; int b = 10; printf("%d + %d = %d\n", a, b, add(a, b)); printf("%d - %d = %d\n", a, b, sub(a, b)); printf("%d / %d = %d\n", a, b, div(a, b)); printf("%d * %d = %d\n", a, b, mul(a, b)); return 0; }
编译生产可执行文件main以下: g++ main.c -o main -L./ -lcac
linux提供dlopen、dlsym、dlerror和dlcolose函数获取动态连接库的函数。
经过这个四个函数能够实现一个插件程序,方便程序的扩展和维护。
#include <dlfcn.h> 以指定模式打开指定的动态连接库文件,并返回一个句柄给 dlsym()的调用进程
void *dlopen(const char *filename, int flag);
char *dlerror(void);
void *dlsym(void *handle, const char *symbol);
int dlclose(void *handle);//使用dlclose()来卸载打开的库。 Link with -ldl.
flag在linux 下有三种解析方式 RTLD_LAZY 暂缓决定,等有须要时再解出符号 RTLD_NOW 当即决定,返回前解除全部未决定的符号。
做用范围,可与解析方式经过“|”组合使用。
RTLD_GLOBAL:动态库中定义的符号可被其后打开的其它库解析。
RTLD_LOCAL: 与RTLD_GLOBAL做用相反,动态库中定义的符号不能被其后打开的其它库重定位。若是没有指明是RTLD_GLOBAL仍是RTLD_LOCAL,则缺省为RTLD_LOCAL。handle = dlopen(full_path.c_str(), RTLD_LAZY | RTLD_GLOBAL);
void _dlsym(void_handle,const char*symbol)
handle:由dlopen打开动态连接库后返回的指针;
symbol:要求获取的函数或全局变量的名称。
#include <stdio.h> #include <dlfcn.h> #define DLL_FILE_NAME "libcac.so" typedef int (CAC_FUNC)(int, int); //using function = void()(int, int); //c++11 int main() { void *handle; CAC_FUNC func = NULL; char *error; int a = 30; int b = 5; handle = dlopen(DLL_FILE_NAME, RTLD_NOW); if(handle == NULL) { fprintf(stderr, "Failed to open libaray %s error:%s\n", DLL_FILE_NAME, dlerror()); return -1; } *(void **) (&func) = dlsym(handle, "add"); if(func == NULL){ printf("ERROR:%s:dlsym\n", dlerror()); return -1; } printf("%d + %d = %d\n", a, b, func(a, b)); func = (CAC_FUNC)dlsym(handle, "sub"); printf("%d + %d = %d\n", a, b, func(a, b)); func= (CAC_FUNC)dlsym(handle, "div"); printf("%d + %d = %d\n", a, b, func(a, b)); func = (CAC_FUNC)dlsym(handle, "mul"); printf("%d + %d = %d\n", a, b, func(a, b)); dlclose(handle); return 0; }
输出:g++ maindl.cpp -o maindl -ldl
30 + 5 = 35 30 + 5 = 25 30 + 5 = 6 30 + 5 = 150
void *dlsym(void _handle, const char _symbol); 返回值为void (void )&(func)是将函数指针的地址强制转换void类型,而后使用取值,获取dlsym的返回值 实际这个地方没有必要这样,函数指针原本就是地址,能够直接用 func = dlsym(handle, "add");
一、函数的返回值若是是 void 类型的,则表示这个函数的执行结果是没有返回值的; 二、函数的返回值若是是 void* 类型的,则表示返回一个内存地址,这个内存空间存放的数据类型是void类型的,即无类型的,也能够说是万能型的 三、在实际开发中,void* 使用时最终都要强制转换成某种明确的数据类型