动态库总结
研究了几天,对大致使用有了了解。
如果要编写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
上一篇: C++ : Clock skew detected错误解决办法
下一篇: 动态库和静态库