标签:工程
什么是DLL
(跟ddl很相近哈……)
由独立的程序模块创建得到动态链接库(Dynamic Linkable Library)文件,可单独进行编译和测试。只有在EXE 程序确实要调用这些DLL模块的情况下,系统才会将它们装载到内存空间中。
只要遵循约定的DLL接口规范和调用方式,用各种语言编写的DLL都可以相互调用。譬如Windows提供的系统DLL(其中包括了Windows的API),在任何开发环境中都能被调用,不在乎其是Visual Basic、Visual C++还是Delphi。
静态库小测试
生成LIB
// test.h
#ifndef LIB_H
#define LIB_H
extern "C" int add(int x, int y);
#endif
// test.cpp
#include "test.h"
int add(int x, int y)
{
return x + y;
}
编译生成test.lib
,如果是在VS里的话,项目右键->属性->常规->项目默认值->配置类型->静态库,编译即可生成。
调用LIB
#include <stdio.h>
#include <iostream>
#include "..\\..\\test.h" // 路径什么的根据自己电脑的来
#pragma comment( lib, "..\\..\\..\\debug\\test.lib" ) //指定与静态库一起连接
int main(int argc, char* argv[])
{
printf("2 + 3 = %d", add(2, 3));
system("pause");
}
test.h
在这里会作为外部依赖项出现。
经测试,三个文件里函数名必须要统一,否则就算lib能够生成也不能调用。
以上,我很奇怪为什么在生成以及后面调用要多次
#include "test.h"
一旦没有两个工程生成解决方案都会错,哭泣。
动态库小测试
生成DLL之dllexport语句
// test.h
#ifndef LIB_H
#define LIB_H
extern "C" int __declspec(dllexport)add(int x, int y);
#endif
__declspec(dllexport)
语句声明函数add为DLL的导出函数,就是说这个函数可以被其他程序调用,即作为DLL的一个对外函数接口。
反之若是dllimport
,则声明一个导入函数,是说这个函数是从别的DLL导入的。
// test.cpp
#include "test.h"
int add(int x, int y)
{
return x + y;
}
编译生成test.dll
,如果是在VS里的话,项目右键->属性->常规->项目默认值->配置类型->动态库,编译即可生成。
动态调用DLL
#include <stdio.h>
#include <windows.h>
typedef int(*lpAddFun)(int, int); //宏定义函数指针类型
int main(int argc, char *argv[])
{
HINSTANCE hDll; //DLL句柄
lpAddFun addFun; //函数指针
hDll = LoadLibrary("..\\..\\..\\debug\\test.dll");
if (hDll != NULL) {
addFun = (lpAddFun)GetProcAddress(hDll, "add");
if (addFun != NULL) {
int result = addFun(2, 3);
printf("%d", result);
}
FreeLibrary(hDll);
}
return 0;
}
这里不用#include "test.h"
,同时也是种动态调用,可以人为选择需要的函数选择加载、调用和释放。
生成DLL之.def文件
采用模块定义(.def)文件声明,提供了有关被链接程序的导出、属性及其他方面的信息。第一行为dll
的名称,exports
后面为导出的函数名,并指定其序号。
LIBRARY temptest
EXPORTS
add @ 1
有了这个文件以后,前面的test.h
就可以不要了。
可以用
addFun = (lpAddFun)GetProcAddress(hDll, MAKEINTRESOURCE(1));
语句来调用add
函数。
静态调用DLL
与前面的动态相对的,还有静态调用方式。由编译系统完成对DLL的加载和应用程序结束时 DLL 的卸载。
#include <stdio.h>
#include <windows.h>
#pragma comment(lib, "test.lib")
//.lib文件中仅仅是关于其对应DLL文件中函数的重定位信息
extern "C" int __declspec(dllimport) add(int x, int y);
int main(int argc, char* argv[])
{
int result = add(2, 3);
printf("%d\n", result);
return 0;
}
一直报错
error LNK2019
,这里已经把test.lib
和test.dll
拷到工程文件夹下面了。并且动态调用dll可行,除非是lib文件有问题。
错误信息
error MSB8020
项目右键->属性->常规->平台工具集 选择电脑上安装好的版本,如v140
error C3872: “0x3000”
检查一下代码里是不是有中文全角空格,删掉即可。
LNK1107: 文件无效或损坏
附加依赖项误把一个lib项写成了dll
error LNK2019: 无法解析的外部符号 __imp__xxx,该符号在函数 _xxxxx 中被引用
一般这种错误加个函数的lib文件到附加依赖项就好了。
预告
VB调用C++的DLL…铺垫了半天还是不会啊……