浅谈.lib .dll .obj 关系&& .a .so .o关系
一、.obj .exe .dll .lib
(1).obj
- 目标文件,相当于源代码对应的二进制文件。
- obj文件就是用.c .cpp .h文件经过编译器编译之后生成的目标文件。
(2).exe
- 将程序运行所需要的全部.obj文件连接起来,即形成.exe文件。
- 也就是windows下的可执行文件。
- obj只给出了程序的相对地址,而EXE是绝对地址
(3).dll
- .dll是可提供给多个程序同时使用的可执行代码和数据(资源 )的库
- 可简单理解为封装好的.cpp,里面装的是函数的具体实现
- .dll是动态编译出来的程序运行时所需要的库,没有.dll文件,动态编译的程序就不能运行
(4).lib
- .lib是编译程序时所需的,非运行时所需
- .lib分为静态和动态
- 静态.lib包括了方法及其具体实现。
- 动态.lib只有方法的声明,简单来看相当于一个h文件,是对实现部分(.dll文件)的导出部分的声明。作用是告诉链接器具体用到了哪个dll文件,以及定位到dll文件内部的函数具体实现位置。
- 利用静态lib编译出来的程序,运行时不需要.dll文件的支持。
- 利用动态lib编译出来的程序,运行时需要.dll文件提供方法的具体实现
- 实际上:.lib文件可看做是若干个.obj文件的集合
(5)一个C/C++工程需要用到其他.c .h .cpp类库、函数库时,其包含的方式有如下图的几种方式
- 1、最直接的方式就是将该类库的.h .cpp 直接引入到工程中,直接完全编译
- 2、另外的方法是先将该类库生成为一个静态的lib库,引入工程时只需包含.h以及.lib文件,编译时将所需的方法具体实现从.lib中提取到可执行文件,可执行文件可不需要其他东西的支持就可直接运行
- 3、常用的方法是将该类库生成一个动态的lib库,还有与之对应的.dll文件,引入工程时也只需包含.h以及.lib文件,但这个动态的.lib文件仅仅提供方法的声明,具体的实现被打包在.dll文件中,因此运行生成的可执行文件需要.dll文件的支持
实战:
1)动态库的生成(lib和dll)
a、新建项目,win32,win32项目,输入项目名称,例如makedll2
b、选择dll、导出符号
c、自动生成makedll2.h
- #define MAKEDLL2_API __declspec(dllexport)表明这些东西可以被外部函数使用,即(dllexport)是把DLL中的相关代码(类,函数,数据)暴露出来为其他应用程 序使用
- class MAKEDLL2_API Cmakedll2 表示导出类,这个类为Cmakedll2类
- extern MAKEDLL2_API int nmakedll2; 声明导出变量
- MAKEDLL2_API int fnmakedll2(void); 声明导出函数
// 下列 ifdef 块是创建使从 DLL 导出更简单的
// 宏的标准方法。此 DLL 中的所有文件都是用命令行上定义的 MAKEDLL2_EXPORTS
// 符号编译的。在使用此 DLL 的
// 任何其他项目上不应定义此符号。这样,源文件中包含此文件的任何其他项目都会将
// MAKEDLL2_API 函数视为是从 DLL 导入的,而此 DLL 则将用此宏定义的
// 符号视为是被导出的。
#ifdef MAKEDLL2_EXPORTS
#define MAKEDLL2_API __declspec(dllexport)
#else
#define MAKEDLL2_API __declspec(dllimport)
#endif
// 此类是从 makedll2.dll 导出的 类名为Cmakedll2
class MAKEDLL2_API Cmakedll2 {
public:
Cmakedll2(void);
// TODO: 在此添加您的方法。
};
//声明导出变量
extern MAKEDLL2_API int nmakedll2;
//声明导出函数
MAKEDLL2_API int fnmakedll2(void);
d、makedll2.cpp
- 导出内容的具体实现
// makedll2.cpp : 定义 DLL 应用程序的导出函数。
//
#include "stdafx.h"
#include "makedll2.h"
// 这是导出变量的一个示例
MAKEDLL2_API int nmakedll2=0;
// 这是导出函数的一个示例。
MAKEDLL2_API int fnmakedll2(void)
{
return 42;
}
// 这是已导出类的构造函数。
// 有关类定义的信息,请参阅 makedll2.h
Cmakedll2::Cmakedll2()
{
return;
}
e、构建
f、检查生成的.dll和.lib
2)动态库的使用
方式一、vs2013下进行项目配置
a、新建一个win32控制台项目
b、在属性管理器中,双击debug或者release
将包含目录设置为刚刚生成dll项目的头文件.h所在文件夹
将库目录设置为刚刚生成dll项目的debug文件夹,也就是.lib所在的文件夹
c、在链接器--->输入页面中,在附加依赖项中添加刚刚生成的.lib文件
c、新建main.cpp文件,对刚刚封装的库进行调用
#include<iostream>
using namespace std;
#include"makedll2.h"
int main()
{
Cmakedll2 testdll; //这个是刚刚封装成lib里面的导出类
//输出导出变量
cout <<"这个是导出变量:"<< nmakedll2 << endl;
//调用的导出函数
cout << "调用导出函数输出:" << fnmakedll2() << endl;
system("pause");
return 0;
}
d、点击运行,应该会报错如下:
e、将上面生成的库.dll文件复制到这个项目的debug下
f、运行,得到如下结果:
方式二、直接在项目中添加lib文件【适用于lib文件较少的情况】
a)新建完项目后,项目视图中右键,添加,现有项,选择所生成的lib文件即可
b)库的.h头文件放在项目目录下
c)库的.dll文件放在项目的debug目录下
方式三、 直接在源文件中加入代码
#pragma comment(lib, "makedll2.lib")
这里引用https://www.cnblogs.com/qinguoyi/p/7257353.html的总结,
动态库使用方法总结
.h,.lib,.dll的添加方法其实各有很多种。
.h有两种:
1. 头文件较少时,直接放在工程目录下,#include "*.h"
2. 建立include文件夹,放在里面,然后在项目属性的“VC++目录”-》“包含目录”,添加.h路径即可。
.lib的方法有两种
1.lib文件较少时,直接放在工程目录下,#pragma comment(lib, "testCpp.lib")
2.建立lib文件夹,目属“VC++目录”-》“库目录”添加路径,然后在项目属性的“链接器”-》“输入”-》“附加依赖项”,添加.lib名字。
dll的方法有两种
1.直接放在debug/release目录下
2.建立bin文件夹,放在里面,然后在项目“环境”中添加bin的路径(PS:最好不要用这个)
3)静态库的生成和使用可参考动态库,使用时不再需要将.dll文件复制到exe目录,因为静态编译将exe所需的内容都提取到exe里面了。
二、.a .so .o
(1).o
- 目标文件,相当于windows下的.obj
- 是编译得到的结果,即源码编译后得到的二进制文件
(2).a
- 静态库文件
- 相当于windows下的静态.lib
- 相当于一个或多个.o文件的集合,可直接由.o文件生成
- .a的命名格式:lib+函数库名+.a
- 构建.a静态库方法:使用ar工具
- 使用.a静态库方法:gcc生成可执行文件时,使用-l(小写)参数指定要加入的库函数。也可以用ld命令的-l和-L参数
- 使用举例:gcc -o hello main.c -L. –l库名 #-L 后面指定静态库路径 -l不用空格后直接加静态库名(lib后面的东西)
(3).so
- 动态库文件,一般叫共享库,share
- 相当于windows下的.dll
- .so的命名格式:lib+函数库名+.so+版本号信息(但是记住,非常底层的C库函数都不是以lib开头命名的)
- 构建.so动态库方法:gcc -fPIC -shared -o lib库名.so.1 atoi.c
- 使用.so动态库方法:gcc -o main main.o -Wl,-rpath=. lib库名.so.1 #-Wl,-rpath:指定库所在路径
- 查看可执行文件所依赖的动态库情况:ldd 可执行文件