Windows 动态库编程技术 C++ 库文件三种模式: lib、dll、dll+lib详解及其创建使用

       动态链接库为模块化应用程序提供了一种方式,使得更新和重用程序更加方便,当几个应用程序在同一时间使用相同的函数时,它也帮助减少内存消耗,这是因为虽然每个应用程序有独立的数据拷贝,但是它们的代码是共享的。

C++ 库会涉及到三个东西: .h .lib .dll文件。

库的使用方式有三种:

1>. .h + .lib 

2>. .dll

3>. .h + .lib + .dll 

第三种方式是最常见的,第一种次之,第二种较少用。

(下面实例使用vs2013)

1>. .h + .lib 

     lib中存放了函数名及具体的函数实现代码,编译器链接时,链接lib文件到exe可执行程序中。

      a. 创建库lib项目exampleLibFile:  新建项目,选择-->Win32 控制台应用程序,应用类型选择-->静态库 , 附加选项: 选择--> 空项目取消预编译头和安全开发生命周期检查,(选择控制台应用程序在项目,在项目属性修改下 --常规--配置类型--中选择--静态库(.lib) 也可以创建lib项目)。

         

b. 创建库lib代码:

  添加 .hpp 和 .cpp  文件( myLib.hpp   myLib.cpp )

//.h 头文件

void go();
int add(int a, int b);
// cpp 文件
#include <stdio.h>
#include <windows.h>

void go() {
	MessageBox(NULL, "我的来自lib的对话框", "Hello Lib", MB_OK);
}

int add(int a, int b) {
	return a + b;
}

c. 编译生成  exampleLibFile.lib 文件。

d. 调用者项目中使用  myLib.hpp 和 exampleLibFile.lib 文件。

#include <stdio.h>
#include "myLib.hpp"

#pragma comment(lib,"../Debug/exampleLibFile.lib")

int main(void) {
	go();

	printf("来自lib的Add函数:%d\n", add(1, 2));

	system("pause");
	return 0;
}

 

2>. dll (使用 winapi调用)

      dll中存放了函数名及具体的函数实现代码,运行时exe可执行程序通过winapi加载dll库文件。

      a. 创建库dll项目exampleDllFile:  新建项目,选择-->Win32 控制台应用程序,应用类型选择-->静态库 , 附加选项: 选择--> 空项目取消预编译头和安全开发生命周期检查,(选择控制台应用程序在项目,在项目属性修改下 --常规--配置类型--中选择--静态库(.lib) 也可以创建lib项目)。

           

b. 创建库dll代码:

  添加 .hpp 和 .cpp  文件( classDll.hpp   classDll.cpp  测试导出类, myDll.c测试导出函数)

//myDll.c


#include <stdio.h>
#include <windows.h>

//如果需要生成可供外部程序调用的函数,必须用dllexport

_declspec(dllexport) void go() {
	MessageBox(NULL, "我是来自dll", "hello Dll", MB_OK);
}



//文件名为c 和 cpp, 生成的函数名字不同,因为C++有函数名重载机制,C没有 
//cpp file
//void go(int a) {
//
//}
//
//void go(int a, double b) {
//
//}
//classDll.hpp文件

//导出类和导出函数一样 需要在前面加 __declspec(dllexport) 这是windows特有的
//库中定义的类和函数 会被两个项目使用 即原来dll项目和调用者项目
//所以要通过宏 预处理指令来实现库中定义的类和函数能被两个项目使用

//这里的.hpp 头文件会被分成两个文件 一个嵌入编译dll库文件中 另一个以.h文件方式供调用者使用
//在创建库项目时vs 编辑器会默认为库项目添加预处理宏: EXAMPLEDLLFILE_EXPORTS, (项目名_EXPORTS),这宏也可以手动添加。

//根据这个预处理宏来区别这个头文件是在dll库中使用还是在调用者项目中使用 
#ifdef _WIN32 // WIN32知识 32位程序 _WIN64 _WIN32不区分32位和64
#ifdef EXAMPLEDLLFILE_EXPORTS  //代表是库文件  dllexport: 导出
#define DLL_API __declspec(dllexport)
#else  //代表调用者文件  dllimport: 导入
#define DLL_API __declspec(dllimport)
#endif
#else   //linux 为空
#define DLL_API
#endif


class DLL_API ClassDll {
public:
	ClassDll();
	~ClassDll();
	static int count;
};
// classDll.cpp文件
#include <iostream>
#include "classDll.hpp"

using namespace std;

int ClassDll::count = 0;

ClassDll::ClassDll() {
	cout << "ClassDll Create" << endl;
}


ClassDll::~ClassDll() {

}

c. 编译生成  exampleDllFile.lib   exampleDllFile.dll文件。

d. 调用者项目中使用  exampleDllFile.dll 文件。

//main.cpp

#include <stdio.h>
#include <windows.h>

//dll  windows api调用方式

int main(void) {
	HMODULE myDll = LoadLibrary("exampleDllFile1.dll");
	if(NULL != myDll) {
		GetProcAddress(myDll, "go")();
	}
	else {
		printf("没有找到dll");
	}

	system("pause");
}

 

3>. .h + .lib + .dll 

    调用库的时候,要有两个文件 lib 和 dll, lib 中记录函数名及函数名对应的地址,dll中记录函数的实现代码。

  a. 创建库dll项目exampleDllFile: 同 2>. dll (使用 winapi调用) 创建dll项目一样。

  b. 创建库dll代码: 同 2>. dll (使用 winapi调用)创建库dll代码一样。

  c. 编译生成  exampleDllFile.lib   exampleDllFile.dll文件。(注意这里的lib文件虽然和第一种lib库文件后缀名相同,但包含的内容格式不一样,这地方lib只有函数名及对应地址, 文件往往就几k大小)

  d. 调用者项目中使用 classDll.hpp  exampleDllFile.lib exampleDllFile.dll 文件。

#include <iostream>
#include <windows.h>
#include "classDll.hpp"

using namespace std;

int main(int argc, char *argv[]) {
	ClassDll cl;
	cl.count++;
	cout << "count = " << cl.count << endl;
	getchar();
	return 0;
}

  

 

 

 在同一个解决方案中创建库和调用程序时,最好设置项目依赖关系 方便开发:

     如:  设置项目b依赖项目a,  那么当编译项目b时, 要确保项目a是最新的,如果不是将先编译项目a。

           

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值