[TOC]
# 概念
我们开发时候经常有一些公共代码是需要反复使用,就把这些代码编译为库文件
库可以简单看成一组目标文件的集合,将这些目标文件经过压缩打包之后形成的一个文件.像在windows这样的平台上,最常用的c语言库是由集成按开发环境所附带的运行库,这些库一般由编译厂商提供
# windows下静态库创建和使用
## 创建
1. 创建一个新项目,在已安装的模板中选择"常规",在右边的类型下选择"空项目",在名称和解决方案名称中输入staticlib.点击确定
2. 在解决方案资源管理器的头文件中添加mylib.h文件,在源文件添加mylib.c文件(即实现文件)

3. 在mylib.h文件中添加如下代码
~~~
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
int myAdd(int a, int b);
#ifdef __cplusplus
}
#endif
~~~
4. 在mylib.c文件中添加如下代码
~~~
#include "mylib.h"
int myAdd(int a, int b)
{
return a + b;
}
~~~
5. 配置项目属性.因为这是一个静态链接库,所以应在项目属性的"配置属性"下选择"常规",在其下的配置类型中选择静态库(.lib)

6. 编译生成新的解决方案,在Debug文件夹下会得到mylib.lib(对象文件库),将该.lib文件和相应头文件.h给用户,用户就可以使用该库里的函数了

文件在这里

## 使用
方法一: 配置项目属性
A. 添加工程的头文件目录:工程-属性-配置属性-c/c++--常规--附加包含目录:加上头文件存放目录
B: 添加文件引用的lib静态库路径:工程--属性--配置属性--链接器--常规--附加库目录:加上lib文件存放目录
C: 然后添加工程引用的lib文件名:工程--属性--配置属性--链接器--输入--附加依赖项:加上lib文件名
方法二: 使用编译语句
~~~
#pragma comment(lib, "./mylib.lib")
~~~
方法三: 添加工程
就像你添加.h和.c文件一样,把lib文件添加到工程文件列表中去.
切换到"解决方法视图"-->选中要添加lib的工程-->点击右键-->添加-->现有项-->选择lib文件-->确定
测试下
~~~
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include"mylib.h"
int main() {
int a = 10;
int b = 20;
int ret = myAdd(a, b);
printf("%d\n", ret);
system("pause");
return EXIT_SUCCESS;
}
~~~
## 优缺点
* 静态库对函数库的链接是放在编译时期完成的,静态库在程序的链接阶段被复制到了程序中,和程序运行时没有关系
* 程序在运行时与函数库再无瓜葛,移植方便
* 浪费空间和资源,所有相关的目标文件与牵扯到的函数库被链接合成一个可执行文件
空间浪费是一个问题,另一个问题是静态链接对程序的更新,部署和发布也会带来很多麻烦.比如程序中使用的mylib.lib是由一个第三方厂商提供的,当该厂商更新容量mylib.lib的时候,那么我们的程序就要拿到最新版的mylib.lib,然后将其重新编译进我们的代码
# windows下动态库创建和使用
等程序运行的时候才链接,把链接过程推迟到了运行时再进行
## 创建
1. 创建一个新项目,在已安装的模板中选择"常规",在右边的类型下选择"空项目",在名称和解决方案名称中输入mydll点击确定
2. 在解决方案资源管理器的头文件中添加mydll.h,在源文件添加mydll.c文件(即实现文件)
3. 在mydll.h文件中添加如下代码
~~~
#pragma once
#ifdef __cplusplus
extern "C"{
#endif // __cplusplus
//内部函数,外部函数
//外部函数.要声明,不声明只能内部使用
__declspec(dllexport) int myAdd(int a, int b);
#ifdef __cplusplus
}
#endif // __cplusplus
~~~
4. 在mydll.c文件中添加如下代码
~~~
#include"mydll.h"
int myAdd(int a, int b)
{
return a + b - 10;
}
~~~


**他会生成个lib文件,这个lib文件和静态库不同的地方在于,静态库的lib是实现,动态库是那些实现是导出的
dll是真正代码实现**
把lib,dll,.h文件拷贝出来
## 使用
方法一: 隐式调用
创建主程序TestDll,将mydll.h, mydll.dll和mydll.lib复制到源代码目录下.(ps: 头文件Func.h不是必须的,只是c++中使用外部函数时,需要先进行声明)在程序中指定链接引用链接库
~~~
#pragma comment(lib, "./mydll.lib")
~~~
方法二: 显示调用
~~~
HANDLE hDll; //声明一个dll实例文件句柄
hDll = LoadLibrarv("mvdll.dll"); //导入动态链接库
MYFUNC minus_test; //创建函数指针
//获取导入函数的函数指针
minus_test = (MYFUNC)GetProcAddress(hDll, "myminus");
~~~
- c语言
- 基础知识
- 变量和常量
- 宏定义和预处理
- 随机数
- register变量
- errno全局变量
- 静态变量
- 类型
- 数组
- 类型转换
- vs中c4996错误
- 数据类型和长度
- 二进制数,八进制数和十六进制数
- 位域
- typedef定义类型
- 函数和编译
- 函数调用惯例
- 函数进栈和出栈
- 函数
- 编译
- sizeof
- main函数接收参数
- 宏函数
- 目标文件和可执行文件有什么
- 强符号和弱符号
- 什么是链接
- 符号
- 强引用和弱引用
- 字符串处理函数
- sscanf
- 查找子字符串
- 字符串指针
- qt
- MFC
- 指针
- 简介
- 指针详解
- 案例
- 指针数组
- 偏移量
- 间接赋值
- 易错点
- 二级指针
- 结构体指针
- 字节对齐
- 函数指针
- 指针例子
- main接收用户输入
- 内存布局
- 内存分区
- 空间开辟和释放
- 堆空间操作字符串
- 内存处理函数
- 内存分页
- 内存模型
- 栈
- 栈溢出攻击
- 内存泄露
- 大小端存储法
- 寄存器
- 结构体
- 共用体
- 枚举
- 文件操作
- 文件到底是什么
- 文件打开和关闭
- 文件的顺序读写
- 文件的随机读写
- 文件复制
- FILE和缓冲区
- 文件大小
- 插入,删除,更改文件内容
- typeid
- 内部链接和外部链接
- 动态库
- 调试器
- 调试的概念
- vs调试
- 多文件编程
- extern关键字
- 头文件规范
- 标准库以及标准头文件
- 头文件只包含一次
- static
- 多线程
- 简介
- 创建线程threads.h
- 创建线程pthread
- gdb
- 简介
- mac使用gdb
- setjump和longjump
- 零拷贝
- gc
- 调试器原理
- c++
- c++简介
- c++对c的扩展
- ::作用域运算符
- 名字控制
- cpp对c的增强
- const
- 变量定义数组
- 尽量以const替换#define
- 引用
- 内联函数
- 函数默认参数
- 函数占位参数
- 函数重载
- extern "C"
- 类和对象
- 类封装
- 构造和析构
- 深浅拷贝
- explicit关键字
- 动态对象创建
- 静态成员
- 对象模型
- this
- 友元
- 单例
- 继承
- 多态
- 运算符重载
- 赋值重载
- 指针运算符(*,->)重载
- 前置和后置++
- 左移<<运算符重载
- 函数调用符重载
- 总结
- bool重载
- 模板
- 简介
- 普通函数和模板函数调用
- 模板的局限性
- 类模板
- 复数的模板类
- 类模板作为参数
- 类模板继承
- 类模板类内和类外实现
- 类模板和友元函数
- 类模板实现数组
- 类型转换
- 异常
- 异常基本语法
- 异常的接口声明
- 异常的栈解旋
- 异常的多态
- 标准异常库
- 自定义异常
- io
- 流的概念和类库结构
- 标准io流
- 标准输入流
- 标准输出流
- 文件读写
- STL
- 简介
- string容器
- vector容器
- deque容器
- stack容器
- queue容器
- list容器
- set/multiset容器
- map/multimap容器
- pair对组
- 深浅拷贝问题
- 使用时机
- 常用算法
- 函数对象
- 谓词
- 内建函数对象
- 函数对象适配器
- 空间适配器
- 常用遍历算法
- 查找算法
- 排序算法
- 拷贝和替换算法
- 算术生成算法
- 集合算法
- gcc
- GDB
- makefile
- visualstudio
- VisualAssistX
- 各种插件
- utf8编码
- 制作安装项目
- 编译模式
- 内存对齐
- 快捷键
- 自动补全
- 查看c++类内存布局
- FFmpeg
- ffmpeg架构
- 命令的基本格式
- 分解与复用
- 处理原始数据
- 录屏和音
- 滤镜
- 水印
- 音视频的拼接与裁剪
- 视频图片转换
- 直播
- ffplay
- 常见问题
- 多媒体文件处理
- ffmpeg代码结构
- 日志系统
- 处理流数据
- linux
- 系统调用
- 常用IO函数
- 文件操作函数
- 文件描述符复制
- 目录相关操作
- 时间相关函数
- 进程
- valgrind
- 进程通信
- 信号
- 信号产生函数
- 信号集
- 信号捕捉
- SIGCHLD信号
- 不可重入函数和可重入函数
- 进程组
- 会话
- 守护进程
- 线程
- 线程属性
- 互斥锁
- 读写锁
- 条件变量
- 信号量
- 网络
- 分层模型
- 协议格式
- TCP协议
- socket
- socket概念
- 网络字节序
- ip地址转换函数
- sockaddr数据结构
- 网络套接字函数
- socket模型创建流程图
- socket函数
- bind函数
- listen函数
- accept函数
- connect函数
- C/S模型-TCP
- 出错处理封装函数
- 多进程并发服务器
- 多线程并发服务器
- 多路I/O复用服务器
- select
- poll
- epoll
- epoll事件
- epoll例子
- epoll反应堆思想
- udp
- socket IPC(本地套接字domain)
- 其他常用函数
- libevent
- libevent简介