win32 静态库和动态库的使用

创建静态库

然后直接创建一个.h文件一个.cpp文件实现静态库中功能

libTest.c

#pragma once
extern int num;
int Add(int a, int b);

libTest.cpp

#include "libTest.h"
int num = 100;
int Add(int a, int b)
{
	return a + b;
}

然后直接运行就会在debug生成文件夹中有一个.lib文件

如何使用静态库?

将静态库中的.h文件一个生成的.lib文件拷贝到要使用的工程文件中

将静态库使用的.h文件添加到项目中

使用静态库

#include "stdafx.h"
#include <stdio.h>

#include "libTest.h"     //静态库头文件
#pragma comment(lib,"静态库.lib")    //包含静态库

int main()
{
	printf("num=%d\n", num);             //使用静态库中的全局变量
	printf("Add(1,2)=%d\n",Add(1,2));    //使用静态库中函数
	

	getchar();
    return 0;
}

动态库

创建方法同创建静态,静态库改为DLL

编写动态库代码

DllTest.h

#pragma once
//在动态库中的全局变量是不能被使用的(无法解析的外部符号)
extern _declspec(dllexport) int num;
//使用动态库需要加上_declspec(dllexport) 只要保证在函数前面就可以 
//函数钱还需要加上extern "C" 防止C++改变函数名的问题
extern "C" _declspec(dllexport) int Add(int a, int b);

//动态库中使用类注意事项:
//需要在类前面加上 _declspec(dllexport) 或者在成员函数名前加上_declspec(dllexport) 
//这两种方式任选其一都ok,不然就是无法解析的外部符号

//☆☆☆☆☆最关键的☆☆☆☆☆
//使用动态库中的类只能通过隐式调用的方式(也就是#pragma comment(lib,"动态库.lib"))
//使用显示调用(LoadLibrary())的方式是不可以的,都是无法解析的外部符号,即使是通过函数返回类指针对象之后
//使用该指针调用类的成员函数同样是无法解析的外部符号
class A;
extern "C" _declspec(dllexport) A* CreateA(); 

class _declspec(dllexport)A										//在类名前加 _declspec(dllexport)
{
public:
	int Multi(int a, int b);				 //或者在成员函数前加 _declspec(dllexport)
};

DllTest.cpp

#include "stdafx.h"
#include "DllTest.h"
#include <iostream>
using std::nothrow;

int num = 100;
int Add(int a, int b)
{
	return a + b;
}

A* CreateA()
{
	A* pA = new(nothrow) A();
	if (pA == NULL)
	{
		printf("实例化对象失败\n");
	}
	return pA;
}

int A::Multi(int a, int b)
{
	return a*b;
}

使用动态库

新建win32项目—>控制台应用程序—>空项目

将生成的.dll文件、.lib文件以及使用的.h文件拷贝到使用的项目中,将头文件添加至工程,具体过程如下

1、添加工程的头文件目录:工程—属性—配置属性—c/c++—常规—附加包含目录:加上头文件存放目录。

 2、添加文件引用的lib静态库路径:工程—属性—配置属性—链接器—常规—附加库目录:加上lib文件存放目录。

 3、添加工程引用的dll动态库:把引用的dll放到工程的可执行文件所在的目录下。

隐式调用动态库

需要.dll动态库文件、.lib导入库文件

第一种方式:#pragma comment(lib,xxx.lib)

//隐示调用方式使用动态库
//就很简单了.在生成DLL的时候.会对应生成lib.我们直接使用这个lib即可.跟直接使用静态lib库一样.
//但是需要注意我们也需要DLL
//这个lib库只是辅助信息.并不跟上面你的静态库lib一样.上面的静态库lib里面是有实质性的代码的.
#include "stdafx.h"
#include "DllTest.h"
#pragma comment(lib,"动态库.lib")
#include <stdio.h>

int main()
{
	//printf("num=%d\n",num);				//不能使用动态库中的全局变量
	printf("Add(1,2)=%d\n", Add(1, 2));		//使用动态库中的函数
	A a;									//使用动态库中的类
	printf("%d\n", a.Multi(2, 3));	

	A* pA = CreateA();						//使用动态库函数中创建的类对象
	printf("%d\n", pA->Multi(3, 4));
	getchar();
    return 0;
}

 第二种方式

直接在VS IDE中添加依赖项

显式调用动态库(不能使用类)

只有.dll动态库文件就可以了

//显示方式调用使用动态库
#include "stdafx.h"
#include "DllTest.h"
#include <stdio.h>
#include <Windows.h>

typedef int(*pAddFun)(int, int);
typedef A* (*pCreateFun)();
int main()
{
	//加载动态库
	HMODULE hModule = LoadLibrary(L"动态库.dll");
	//获取动态库中的函数指针
	pAddFun pAdd = (pAddFun)GetProcAddress(hModule, "Add");
	printf("Add(1,2)=%d\n", pAdd(1, 2));	//或者使用 (*pAdd)(1,2)也是一样的
	
	//不能使用类,无法解析的外部符号
	//pCreateFun pCreate = (pCreateFun)GetProcAddress(hModule, "CreateA");
	//A* pA = pCreate();
	//printf("a.Multi(2, 3)=%d\n", pA->Multi(2, 3));
	getchar();
	return 0;
}

静态库和动态库的区别

静态库在汇编的时候将代码和exe文件联系起来,所以会导致生成的exe文件增大,链接之后可以将.lib的静态库文件删除了

动态库只是在需要的时候进行调用动态库中的内容,不会导致exe文件增大,但是在工程目录中要一直保留使用的动态库文件

动态库一般会有对应的导入库(.lib文件),方便程序静态载入动态链接库,如何没有导入库的话,那么只能通过显示调用的方式使用动态库了,自己加载动态库LoadLibrary(),自己获取动态库中的函数地址GetProcAddress()

有了导入库,只需要链接导入库后,按照头文件中的函数声明调用就可以了

导入库和静态库的区别

静态库包含了实际执行代码 、符号表等

导入库只有符号表地址这些了,保证程序找到对应函数的一些基本地址信息,代码是在动态库中的

动态库优点

DLL有助于共享数据和资源,多个应用程序可同时访问内存中DLL副本的内容

利于升级

静态库优点

静态库代码装载速度快,不需要考虑用户计算机上静态库文件是否存在

其他

debug和release的工程和动态库混合使用不影响

x64应用程序不能调用x32库,反之也一样,不能混合使用

如果想要使用64位程序使用32位的库有以下解决方案:

64位进程调用32位dll的解决方法 - 3D入魔 - 博客园

64位程序如何调用32位dll(简单解决方案 ) - it610.com

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值