Windows下静态库与动态库的制作与使用

本文介绍了在Windows操作系统下如何制作和使用静态库及动态库。内容涵盖函数和类的静态库、函数的动态库、全局变量的动态库以及类的动态库的制作步骤,并详细阐述了动态库的静态加载方法,特别指出在工程中由于只支持UNICODE字符导致的问题及其解决方案。
摘要由CSDN通过智能技术生成
为了代码的共享和可重用,将一些需要反复使用的代码制作成库文件,有两种类型的库文件:静态库和动态库。
静态库和动态库是两种共享程序代码的方式,它们的区别是:静态库在程序的链接阶段被复制到了程序中,和程序运行的时候没有关系;动态库在链接阶段没有被复制到程序中,而是程序在运行时由系统动态加载到内存中供程序调用。使用动态库的优点是系统只需载入一次动态库,不同的程序可以得到内存中相同的动态库的副本,因此节省了很多内存。
使用静态库文件,在链接过程中,将库内的代码完整进行拷贝复制到程序中,生成EXE可执行文件,优点是,EXE可以脱离环境执行,(一次编译,处处执行),因为已包含所有的lib代码。缺点是,可扩展性差,当lib功能扩展之后,需要重新编译链接EXE文件。以及多次使用lib就会有多分冗余的拷贝。

·································Windows下·······························

制作与使用函数 和类 静态库

制作:第一步 建立static library工程
          第二步 头文件申明函数,或者类。 源文件中实现函数体,或者类方法。(除模板类不支持实现定义的分开)
          第三步 编译 链接 在工程路径/debug/下 生成 .lib 文件
使用:第一步 包含库文件的头文件(用户知道了如何调用,但不知道具体实现)
          第二步 库lib文件 放入控制台的工程路径下
          第三步 引入#pragma comment (lib,"静态库文件名“)   //没有分号
          第四步 编译 链接 执行生成.exe文件(一次编译,处处执行)

制作与使用函数动态库

制作:第一步 建立Dynamic_link library 工程

      第二步 头文件申明函数,若申明成普通函数,则只可在当前工程下调用,相当于动态库的内部函数

                             若申明成导出函数,除生成.dll文件外,还生成相应的.lib文件,供外部调用

      第三步 编译链接 生成.dll以及.lib文件

使用:静态加载  (需动态库中的函数为导出函数 ——declspec(dllexport)   )

            第一步 将.dll  以及.lib以及.h文件包含在控制台工程中。

            第二步 引入#pragma comment (lib,"静态库文件名“)   //没有分号

            第三步 编译 链接 执行生成.exe文件(若脱离此dll以及.lib所在的工作环境,.exe则不能执行)

   动态加载 (#include<windows.h>需要求函数声明为c编译方式的导出函数 extern "c" int __declspec(dllexport)add(int a,int b) ,则此函数用c方式编译,不能重载)
            第一步 将.dll文件以及.h文件包含在控制台工程中。
            第二步 创建句柄
            第三步 加载动态库 LoadLibrary("动态库文件名“)
            第四步 获取动态库内的函数 使用句柄接收 GetProcAddress(句柄名,"函数名");
            第五步 使用句柄调用函数
            第六步 卸载动态库 FreeLibrary(句柄)
示例:
动态库内容:
使用动态库的控制台工程源文件:
#include "test.h"
#include <iostream>
#include <Windows.h>
using namespace std;
typedef int(*pfun)(int, int);//定义一个函指针	int(*padd)(int, int)
int main()
{
	HINSTANCE hdll;
	hdll = LoadLibrary("test_dll.dll");
	if (hdll == NULL)
	{
		cout << "load library error!" << endl;
		return;
	}
        pfun padd= (pfun)GetProcAddress(hdll, "add");
	if (padd == NULL)
	{
		cout << "get fun error!" << endl;
	}
	else
	{
		cout << "add(2,3):" << padd(2, 3) << endl;
	}
	FreeLibrary(hdll);

}
若出现:error C2664: “HMODULE LoadLibraryW(LPCWSTR)”: 无法将参数 1 从“const char [13]”转换为“LPCWSTR”错误

原因 :工程只支持UNICODE字符

解决方法:

1、工程属性->配置属性-->常规--->字符集---->使用多字节符字符集
结果:add(2,3):5


制作与使用全局变量动态库

制作:在动态库工程中
                         第一步 头文件中申明导出全局变量
                         第二步 源文件中定义全局变量
                         第三步创建模块定义文件  文件名与动态库文件名相同  后缀为.def
                         第四步 将test_dll.def加载到动态库工程中,编译链接生成.dll和.lib文件
使用: 在控制台工程中
                        第一步 静态加载动态库#pragma comment(lib,"test_dll.lib")
                        第二步申明导入动态库中的全局变量extern int —declspec(dllimport) g_global;
                        第三步使用时 g_global只代表一个地址 需强转成指针再解引用

制作与使用动态库



制作:在动态库工程中
                       第一步 头文件中申明为导出类 class __declspec(dllexport)stack
                       第二步 源文件中实现类方法  则素有的方法都为导出方法
                       第三步 编译链接生成.dll .lib文件
使用:在控制台工程中
                       第一步 将.dll  .lib  .h包含在工程目录下
                       第二步 静态加载动态库  #pragma comment(lib,"test_dll.lib") 
                       第三步 直接用!
示例:
头文件:
class __declspec(dllexport)stack
{
public:
	stack(int sz);
	~stack();
public:
	bool push(int a);
	bool pop();
	bool isfull()const;
	bool isempty()const;
	bool show();
private:
	int *data;
	int top;
	int size;
};
源文件:
#pragma comment(lib,"test_dll.lib")
//extern int __declspec(dllimport) g_global;

void main()
{
	stack s(5);
	s.push(1);
	s.push(2);
	s.push(3);
	s.show();
}
动态库中源文件:
#include <iostream>
#include "test.h"
using namespace std;

int add(int a, int b)
{
	return a + b;
}
int sub(int a, int b)
{
	return a - b;
}
int mul(int a, int b)
{
	return a*b;
}

int g_global = 10;

bool stack::isfull()const
{
	return top >= size;
}
bool stack::isempty()const
{
	return top == 0;
}
stack::stack(int sz)
{
	size = sz;
	data = new int[size];
	top = 0;
}
stack::~stack()
{
	delete[]data;
	data = NULL;
	size = top = 0;
}

bool stack::push(int a)
{
	if (isfull())
	{
		return false;
	}
	data[top++] = a;//先赋值后++
	return true;
}
bool stack::pop()
{
	if (isempty())
		return false;
	top--;
	return true;
}
bool stack::show()
{
	for (int i = 0; i < top; ++i)
	{
		cout << data[i] << endl;
	}
	return true;
}





评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值