静态库、动态库的含义、生成及使用教程

首先介绍一下静态库(静态链接库)、动态库(动态链接库)的概念,首先两者都是代码共享的方式。

静态库:在链接步骤中,连接器将从库文件取得所需的代码,复制到生成的可执行文件中,这种库称为静态库,其特点是可执行文件中包含了库代码的一份完整拷贝;缺点就是被多次使用就会有多份冗余拷贝。即静态库中的指令都全部被直接包含在最终生成的 EXE 文件中了。在vs中新建生成静态库的工程,编译生成成功后,只产生一个.lib文件

动态库:动态链接库是一个包含可由多个程序同时使用的代码和数据的库,DLL不是可执行文件。动态链接提供了一种方法,使进程可以调用不属于其可执行代码的函数。函数的可执行代码位于一个 DLL 中,该 DLL 包含一个或多个已被编译、链接并与使用它们的进程分开存储的函数。在vs中新建生成动态库的工程,编译成功后,产生一个.lib文件和一个.dll文件

那么上述静态库和动态库中的lib有什么区别呢?

静态库中的lib:该LIB包含函数代码本身(即包括函数的索引,也包括实现),在编译时直接将代码加入程序当中

动态库中的lib:该LIB包含了函数所在的DLL文件和文件中函数位置的信息(索引),函数实现代码由运行时加载在进程空间中的DLL提供

总之,lib是编译时用到的,dll是运行时用到的。如果要完成源代码的编译,只需要lib;如果要使动态链接的程序运行起来,只需要dll

生成和使用动态库

生成动态库

 新建项目--win32项目--填写项目名--确定--下一步--应用程序类型:选择dll--附加选项:选择导出符号--完成

可以看到生成了一个dllmain.cpp 文件,这是dll应用程序的入口,注意它和普通工程的入口main函数不同,这个文件我们不需要修改。

 在这个动态库中我们举例导出一个变量,一个类,一个函数,头文件dll.h如下:

// 下列 ifdef 块是创建使从 DLL 导出更简单的
// 宏的标准方法。此 DLL 中的所有文件都是用命令行上定义的 WIN32PROJECT1_EXPORTS
// 符号编译的。在使用此 DLL 的
// 任何其他项目上不应定义此符号。这样,源文件中包含此文件的任何其他项目都会将
// WIN32PROJECT1_API 函数视为是从 DLL 导入的,而此 DLL 则将用此宏定义的
// 符号视为是被导出的。
#ifdef WIN32PROJECT1_EXPORTS
#define WIN32PROJECT1_API __declspec(dllexport)
#else
#define WIN32PROJECT1_API __declspec(dllimport)
#endif

// 此类是从 Win32Project1.dll 导出的
class WIN32PROJECT1_API CWin32Project1 {
public:
	CWin32Project1(void);
	// TODO:  在此添加您的方法。
};

extern WIN32PROJECT1_API int nWin32Project1;

WIN32PROJECT1_API int fnWin32Project1(void);
// Win32Project1.cpp : 定义 DLL 应用程序的导出函数。
//

#include "stdafx.h"
#include "Win32Project1.h"


// 这是导出变量的一个示例
WIN32PROJECT1_API int nWin32Project1=0;

// 这是导出函数的一个示例。
WIN32PROJECT1_API int fnWin32Project1(void)
{
    return 42;
}

// 这是已导出类的构造函数。
// 有关类定义的信息,请参阅 Win32Project1.h
CWin32Project1::CWin32Project1()
{
    return;
}
// 下列 ifdef 块是创建使从 DLL 导出更简单的
// 宏的标准方法。此 DLL 中的所有文件都是用命令行上定义的 WIN32PROJECT1_EXPORTS
// 符号编译的。在使用此 DLL 的
// 任何其他项目上不应定义此符号。这样,源文件中包含此文件的任何其他项目都会将
// WIN32PROJECT1_API 函数视为是从 DLL 导入的,而此 DLL 则将用此宏定义的
// 符号视为是被导出的。
#ifdef WIN32PROJECT1_EXPORTS
#define WIN32PROJECT1_API __declspec(dllexport)
#else
#define WIN32PROJECT1_API __declspec(dllimport)
#endif

// 此类是从 Win32Project1.dll 导出的
class WIN32PROJECT1_API CWin32Project1 {
public:
	CWin32Project1(void);
	// TODO:  在此添加您的方法。
};

extern WIN32PROJECT1_API int nWin32Project1;

WIN32PROJECT1_API int fnWin32Project1(void);

然后在鼠标移至项目处,右键点击生成。

使用动态库

隐式调用①:

1. 将上面创建Dll过程中的头文件(.h),lib文件以及dll文件复制到与项目同名的文件夹下

2. 然后在需要调用的地方直接include头文件,然后直接使用。

静态库、动态库的含义、生成及使用教程_第1张图片

 隐式调用②:

1. 将lib添加到项目属性 链接器 输入附加依赖项

2. 设置项目属性 vc++目录 库目录添加lib所在的路径

3. 设置项目属性 vc++目录 包含目录添加.h所在的路径

4. 将dll放到工程的工作目录(调试--工作目录,可以加到现有工作目录,也可以新建一个加进去)

 显示调用①:

其实lib文件可以不需要,而直接调用dll里面的方法。

采用LoadLibrary和GetProcAddress的方法,那样子可以不需要lib文件。但是有一个重大影响,就是得知道方法名的准确名字。特别是对于c++输出整个类的情形。因为c++输出dll的时候,类的方法名都被打乱了,加入了很多的信息,所以一般情况下是不知道的,得通过def文件来重命名输出的方法名。

我不知道为什么上面那个例子动态调用总是失败,然后换了一个例子可以成功。

#pragma once
#ifndef _DLL_TEST_H_
#define _DLL_TEST_H_
 
#include 
 
namespace DLL_TEST
{
	void PrintHello();
}
 
#endif // !_DLL_TEST_H_
#include "mydll.h"
 
void DLL_TEST::PrintHello()
{
	std::cout << "Hello world!" << std::endl;
}
//mydll.def
LIBRARY Win32Project3
 
EXPORTS 
PrintHello

LIBRARY后跟的是项目名,EXPORTS后是这个dll中需要导出的函数名。同时将mydll.def写入到项目的属性--配置属性--链接器--输入--模块定义文件中去。

显式连接:在函数的参数中能够指定DLL文件的完整路径;若不指定路径,Windows将遵循下面的搜索顺序来定位DLL:
(1)包含EXE文件的目录
(2)工程目录
(3)Windows系统目录
(4)Windows目录
(5)列在Path环境变量中的一系列目录

显示调用借助了windows库,直接在调用程序中写如下代码即可调用:

#include 
#include 
 
int main()
{
	// TODO: Add your control notification handler code here
	HINSTANCE hInst;
	hInst = LoadLibrary(L"dll的名字.dll");
	typedef void(*Sub)();//函数指针
	Sub PrintHello = (Sub)GetProcAddress(hInst, "PrintHello");//从dll中加载函数出来
 
	PrintHello();//运行函数
 
	FreeLibrary(hInst);       //LoadLibrary后要记得FreeLibrary
 
	system("pause");
	return 0;
}
 

生成和使用静态库

1、我们先新建一个项目,选择win32项目

静态库、动态库的含义、生成及使用教程_第2张图片

2、在接下来的应用程序向导中选择静态库并去掉预编译头的勾。

静态库、动态库的含义、生成及使用教程_第3张图片

 3、创建头文件(.h)以及源文件(.cpp),它们的格式如下:

#pragma once
#ifndef _STATIC_LIB_H_
#define _STATIC_LIB_H_
 
#include 
 
namespace STATIC_LIB
{
	void PrintHello();  //测试函数
}
 
#endif
#include "myLib.h"
 
void STATIC_LIB::PrintHello()
{
	std::cout << "Hello world!" << std::endl;
}

4、然后,我们选择release,生成解决方案

5、随后,我们可以在自定的项目路径下的release文件夹下看到生成的lib文件。

1、我们创建一个include文件夹和lib文件夹用来存放头文件和lib文件:

2、项目名那右击,选择属性,在弹出的属性页窗口中选择VC++目录,然后添加进这两个文件夹

静态库、动态库的含义、生成及使用教程_第4张图片

 3、将先前创建lib时的头文件和lib文件分别复制到这两个文件夹中

4、接着,再在属性页面中选择链接器--输入--附加依赖项中添加我们的lib (只用输入lib的名字,不用路径名)

5、准备工作完成,在我们调用的程序中使用如下格式的代码即可调用:

#include 
#include "myLib.h"
 
int main()
{
	STATIC_LIB::PrintHello();
 
	system("pause");
	return 0;
}

你可能感兴趣的:(C++,配置和环境变量等,mfc,microsoft,c++)