欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

动态库总结

程序员文章站 2022-06-09 17:41:27
...

研究了几天,对大致使用有了了解。
如果要编写dll动态库,首先要了解以下的知识,不着急写代码。

需要掌握的知识:

1.预编译头,预处理命令,extern “C”,typedef,#pragmaonce等的解释和使用
2.dll,lib是什么
3.创建dll程序,生成dll或者是lib文件
4.有几种调用dll的方式。显式调用/隐式调用
多看看别人是怎么写的。融合进来。快速参透。
MSDN:https://docs.microsoft.com/zh-cn/cpp/build/dlls-in-visual-cpp?view=msvc-160&viewFallbackFrom=vs-2015

一、lib和dll的定义以及区别

参考:
https://www.cnblogs.com/TenosDoIt/p/3203137.html

dll:动态库。动态链接库是一个包含可由多个程序同时使用的代码和数据的库
lib:静态库。在链接步骤中,连接器将从库文件取得所需的代码,复制到生成的可执行文件中

二者区别:
静态库中的lib:该LIB包含函数代码本身(即包括函数的索引,也包括实现),在编译时直接将代码加入程序当中
动态库中的lib:该LIB包含了函数所在的DLL文件和文件中函数位置的信息(索引),函数实现代码由运行时加载在进程空间中的DLL提供

总之,lib是编译时用到的,dll是运行时用到的。如果要完成源代码的编译,只需要lib;如果要使动态链接的程序运行起来,只需要dll。

二、生成dll/lib

参考:
https://www.cnblogs.com/lanhaicode/p/10798385.html
微软:https://docs.microsoft.com/zh-cn/cpp/build/walkthrough-creating-and-using-a-dynamic-link-library-cpp?view=msvc-140

小细节:
如果只有.h使用了_declspec(dllexport)那么就只会生成dll文件
如果.cpp也使用了_declspec(dllexport)那么就会生成dll文件,也有lib文件

1.预处理命令的使用详解-#if,#endif,#undef,#ifdef,#else,#elif
参考:https://www.cnblogs.com/lanhaicode/p/10546514.html

2.extern "C"的作用详解
参考:extern “C”是指示编译器这部分代码按C语言(而不是C++)的方式进行编译

三、调用dll

1.显式调用
只使用.dll
显示调用必须使用extern "C"修饰符修饰函数。隐式调用可以使用任何类型

2.隐式调用
只使用.h+.lib+.dll
添加头文件,依赖库,和动态链接库才能成功编译工程。

参考代码:
创建dll动态库工程即可。
dll .h

/*!
* Copyright (C) 2021 爱做尼啊
* 版权所有。
* 代码仅用于实验
\file: my_dll.cpp
\brief dll头文件
\author wqj
\Date 2021/5
*/
#pragma once
//和#pragma once/二选一
//下面这个由语言支持所以移植性好,#pragma once 可以避免名字冲突
#ifndef __MYDLL_H__
#define __MYDLL_H__

//声明--可以使用它们从 DLL 中导出或向其中导入函数、数据和对象
//当编译时,头文件不参加编译,所以.cpp文件中先定义,后头文件被包含进来,
//因此外部使用时,为dllexport,而在内部编译时,则为dllimport
#ifdef MYDLL_EXPORTS
#define MYDLL_API __declspec(dllexport)
#else
#define MYDLL_API __declspec(dllimport)
#endif


//编译器以c语言方式编译该函数
/**
* @brief 计算和
* @param[in] a 输入值
* @param[in] b 输入值
* @return 数据
*/
extern "C" MYDLL_API int sum(int a, int b);

#endif


dll .cpp

#include "stdafx.h"
#include "my_dll.h"
#include <iostream>

extern "C" MYDLL_API int sum(int a, int b)
{
	return a + b;
}



调用代码:

/*!
* Copyright (C) 2021 爱做尼啊
* 版权所有。
* 代码仅用于测试
\file: main.cpp
\brief 演示用文件
\author wqj
\Date 2021/5
*/
#define MOD 1
#include "my_dll.h"
#include <iostream>  
#include <windows.h>
#pragma comment(lib,"MyDll.lib")

//显式链接 
void UseExplicit()
{
	//定义指向dll中函数的函数指针--定义一种类型的别名
	typedef int(*lpfnDllFunc1/*别名*/)(int a, int b);

	HINSTANCE hDLL;
	lpfnDllFunc1 fun;
	//加载DLL文件,找不到则返回空
	hDLL = LoadLibrary("../Debug/MyDll.dll");
	if (NULL != hDLL)
	{
		//获取DLL中导出函数的地址(函数名)
		fun = (lpfnDllFunc1)GetProcAddress(hDLL, "sum");
		if (NULL != fun)
		{
			int a = fun(1, 2);
			std::cout << "a: " << a << std::endl;
		}
		//卸载DLL文件
		FreeLibrary(hDLL);
	}
	else
	{
		std::cout << GetLastError() << std::endl;
		std::cout << "not find dll" << std::endl;
	}
}
//隐式链接
void UseImplicit()
{
	int a = sum(1, 2);
	std::cout << "a:" << a;
}

int main()
{
	if (MOD == 1)
	{
		UseExplicit();
	}
	else {
		UseImplicit();
	}
	
	system("pause");
	return 0;
}

修改时间:2021-05-27

相关标签: 动态库