前言
1、每种方法也要复制相应的DLL文件到相应目录,或者设定DLL目录的位置,具体方法为:"Properties" -> "Configuration Properties" -> "Debugging",在"Working Directory"设置dll的路径就可以了
2、无论是设置DLL目录,或者是Lib目录,亦或是头文件的目录,都有release版本和debug版本的区分,每种版本的设置都是独立的,要分别设置。
一、加载方式
方法1: 通过设置工程配置来添加lib库.
A、添加工程的头文件目录:工程---属性---配置属性---c/c++---常规---附加包含目录:加上头文件存放目录。
B、添加文件引用的lib静态库路径:工程---属性---配置属性---链接器---常规---附加库目录:加上lib文件存放目录。
C 然后添加工程引用的lib文件名:工程---属性---配置属性---链接器---输入---附加依赖项:加上lib文件名。
这种方法比较繁琐,且不直观,而且还可能要争对debug版本和release版本作不同的配置,因为我们生成的两个版本的库可能放在不同的目录中的.
方法2: 使用编译语句:
#ifdef _DEBUG
#pragma comment(lib,"..\\debug\\LedCtrlBoard.lib")
#else
#pragma comment(lib,"..\\release\\LedCtrlBoard.lib")
#endif
这种方法直观,方便,且可以按如上直接区分出Debug版本和Release版本的不同目录.当然,通过宏,还可以区分更多版本.
但是在指定目录时,不小心容易出错.
方法3: 直接添加库文件到工程中.
就像你添加.h和.cpp文件一样,把lib文件添加到工程文件列表中去.
VC中,切换到"解决方案视图",--->选中要添加lib的工程-->点击右键-->"添加"-->"现有项"-->选择lib文件-->确定.
就是这么简单,搞定.
这个方法适用于在我的工程的debug版本和Release版本中都使用同一个lib库文件时.这样就省去了你1方法配置环境的繁琐,也省去了方法2种语句的可能性错误发生.
二、动静加载说明
dll的动态加载,又称显式加载,特点有以下几点:
1:灵活,可以在需要的时候用LoadLibrary进行加载,在不需要的时候用FreeLibrary进行卸载,这样可以不必占用内存。
2:可以在没有dll时候发现,而不致程序报错。
3:加载程序中有条件才运行的库。
4:热更新,在不停止程序的前提下进行更新。
5:复杂一些,需要显式获得函数地址。
6:dll没有对应的lib文件,此时只能进行动态加载。
7:dll动态加载只需要dll文件就可以了,不需要导入库和头文件。
加载方法:
LoadLibrary
GetProcAddress
FreeLibrary
#include <stdio.h>
#include <Windows.h>
#pragma comment(lib, "DllLoad.lib")
int main()
{
HINSTANCE h = LoadLibraryA("DllLoad.dll");
typedef int(*FunPtr)(int a, int b);//定义函数指针
if (h == NULL)
{
FreeLibrary(h);
printf("load lib error\n");
}
else
{
FunPtr funPtr = (FunPtr)GetProcAddress(h, "add");
if (funPtr != NULL)
{
int result = funPtr(8, 3);
printf("8 + 3 =%d\n", result);
}
else
{
printf("get process error\n");
printf("%d", GetLastError());
}
FreeLibrary(h);
}
return 0;
}
dll静态加载,又称隐式加载,需要把库中所有的函数链接到可执行文件中。
1:简单方便;
2:没有dll时,系统报错;
3:加载运行很久的库;
4:dll必需有相应的lib文件;
5:将整个dll库加载到exe中,占用内存较大,但速度较快。
6:dll静态加载需要dll和lib文件以及.h文件。
在调用OpenCV库时,我们就是采用的dll静态加载的方法进行的。
加载方法:
1、确保有a.dll和a.lib,两个文件都有的话可以用静态加载的方式。
2、在.cpp文件中通过#pragma comment(lib, "a.lib") 加载lib,并包含相应的头文件,就可以使用dll中的函数了
Example:
test.h头文件
#ifndef _TEST_H_
#define _TEST_H_
#ifdef NEWDLL_EXPORTS
#define MYDLL_API extern "C" __declspec(dllexport)
#else
#define MYDLL_API extern "C" __declspec(dllimport)
#endif
MYDLL_API int add(int x, int y);
#endif
test.c
#include <stdio.h>
#include "test.h"
int add(int x, int y)
{
return x + y;
}
main.c
#include <stdio.h>
#include "test.h"
#include <Windows.h>
//#pragma comment(lib, "DllLoad.lib")
int main()
{
printf("2 + 3 = %d \n", add(2, 3));
return 0;
}
对test.c进行编译后得到DllLoad.lib和DllLoad.dll,这里通过__declspec(dllexport) 将库中的函数导出。在main.c中可以采用两种方法进行动态库的静态加载。
(1)#pragma comment(lib,"DllLoad.lib")
(2)属性-->配置属性-->链接器-->输入-->附加依赖项中添加DllLoad.lib。
注意此处的.lib文件有一个需要注意的地方是:
- 静态库——函数和数据被编译进一个二进制文件(扩展名.lib)。在使用静态库的情况下,在编译连接可执行文件时,连接器从库中复制这些函数和数据并把他们和应用程序的其他模块组合起来创建最终的可执行文件(.exe)文件,当发布产品时,只需要发布这个可执行文件,并不需要发布被使用的静态库。所以采用静态库链接编译的出来的可执行文件一般比动态库链接编译出来的可执行文件要大很多。
- 动态库——在使用动态库时,往往提供两个文件:一个引入库(.lib)文件和一个DLL(.dll)文件。虽然引入库的后缀名也是".lib",但是,动态库的引入库文件和静态库文件有着本质的区别。对一个dll来说,引入库文件(.lib)包含该DLL导出的函数和变量的符号名,而.dll文件包含该DLL实际的函数和数据,在使用动态库的情况下,在编译连接和执行文件时,只需要连接该DLL的引入库文件,该DLL中的函数代码和数据并不复制到可执行文件中,直到可执行程序运行时,才去加载所需要的DLL,将该DLL映射到进程的地址空间中,然后访问DLL中导出的函数。这时,在发布产品时,除了发布可执行文件以外,同时还要发布该程序将要调用的动态连接库。
注:
关于lib的静态加载和静态加载:
静态加载(.lib):1.目标函数接口和数据在工程项目编译时,以copy的形式,链入。
2.可执行文件大
动态加载(.lib+.dll):1.库文件(.lib)包含该dll导出的函数和变量的符号名
2..dll文件包含该dll实际的函数和数据
3.项目工程编译时,只需链接该dll的引入库文件,不需copy大量函数和数据
4.执行.exe时,才会加载dll,将dll映射到进程的地址空间中 然后访问dll中导出的函数。
三、lib与dll的区别
1. 使用方式有什么不同?
2. 原因是什么?
其实lib无论怎么样,都会用到。
一种是lib单独使用,另外一种是lib+dll的方式(平时所说的dll的方式)。
1.lib单独使用:
1. LIB包含函数代码本身,不仅包含头文件,还有源码,在编译时直接将代码加入程序当中,称为静态链接库static link library。链接生成的程序可以独立运行。
即lib文件是静态编译出来的,索引和实现都在其中。
2. 同一机器,多个同种程序运行,每个程序都会加载一份代码库。
3. 任何改动,都需要重新编译、链接,这个对大型的程序非常不便,升级也麻烦。有时,在更改数据结构时,需要重新编译整个工程,而非只编译、链接单个lib。
2.lib+dll方式:
1. LIB包含了函数所在的DLL文件和文件中函数位置的信息(入口),代码由运行时加载在进程空间中的DLL提供,称为动态链接库dynamic link library。生成的程序需要dll配合使用。
即lib一般是一些索引信息,记录了dll中函数的入口和位置,dll中是函数的具体内容。应用程序使用LIB文件链接到DLL文件。在应用程序的可执行文件中,存放的不是被调用的函数代码,而是DLL中相应函数代码的地址,从而节省了内存资源。
2. 多个程序运行,共享一份代码。节省内存。
3. 当 DLL 中的函数发生更改时,只要函数的参数和返回值没有更改,就不需重新编译或重新链接使用它们的应用程序。
3.使用方式的差别:
1. 静态lib
需要.h和lib。
在生成lib时,相当于cpp编译的obj的集合。链接时,指定lib的位置。
2. 动态lib
实质上是dll的使用方式。
在生成dll时,会生成一个lib,lib里包含的是索引信息。
编译链接时,需要.h,lib。
运行时,需要程序和dll。
有关dll和lib的信息还很多,暂时理解到这个层面吧。
msdn的链接:
http://msdn.microsoft.com/zh-cn/library/dtba4t8b(v=vs.80).aspx
runtime library如何选择?
参考 https://blog.csdn.net/viewcode/article/details/8508211 多线程编程中的操作系统概念