19.2 显式加载/隐式加载--《Windows核心编程》
部分笔记来自于:https://blog.csdn.net/blade1080/article/details/81364161
注:关于DLL存放位置,一般是放到可执行文件的目录下。
下面时加载程序的搜索顺序:
1) 包含可执行映像文件的目录。 2) 进程的当前目录。 3) Windows系统目录。 4) Windows目录。 5) PATH环境变量中列出的各个目录。
显式加载
调用 LoadLibrary/LoadLibrary 函数加载DLL。
隐式加载
是在系统启动时一次性把所有的DLL的导出函数加载到可执行文件中,需要用到.h和.lib文件。
创建DLL动态库
1、新建Dll项目
文件->新建->项目->Visual C++ win32控制台程序(填写项目名MyDll)->下一步->(应用程序类型)勾选:DLL,(附加选项)勾选:空项目->完成
2、添加新建项MyDll.h
#pragma once
#ifdef MYDLL_EXPORTS
#define MYDLL_API __declspec(dllexport)
#else
#define MYDLL_API __declspec(dllimport)
#endif
class MyDll
{
public:
MYDLL_API int Add(int a, int b); // 导出函数
MYDLL_API void myPrint(const char* s);
};
extern "C" MYDLL_API void printStr(const char* s);
extern "C" MYDLL_API extern int num; // 导出变量
dllimport 与 dllexport用于声明导入导出属性,其中_declspec(dllexport)用在dll程序中,用于说明这是导出的函数。而_declspec(dllimport)用在调用dll的程序中,用于说明这是从dll中导入的函数。
3、添加新建项MyDll.cpp
// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "pch.h"
#include "MyDll.h"
#include <iostream>
int num = 10; // 定义变量
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
int MyDll::Add(int a, int b)
{
return a + b;
}
void MyDll::myPrint(const char* s)
{
std::cout << s << std::endl;
}
void printStr(const char* s)
{
std::cout << s << std::endl;
}
4、编译生成
生成结果如下所示

隐式加载方式将使用到MyDll.h、MyDll.lib、MyDll.dll。
MyDll.lib需放置于项目的库搜索路径下,MyDll.dll需放置于项目生成的可执行文件同一目录下。

隐式加载方式使用DLL动态库
隐式加载是在系统启动时一次性把所有的DLL的导出函数加载到可执行文件中,需要用到.h和.lib文件。隐式加载的步骤为:
1、新建测试项目
文件->新建->项目->Visual C++ win32控制台程序(填写项目名testDll)->下一步-> (附加选项)勾选:空项目->完成
2、添加新建项main.cpp文件
注意包含DLL相关的那个头文件
#include <iostream>
#include "MyDll.h" // dll对应的那个头文件
// 在项目属性中添加dll对应.lib路径,附加依赖项里添加dll对应的.lib文件名
// 或者 #pragma comment (lib,"D:/Project Files/MyDll/Debug/MyDll.lib")
int main(void)
{
MyDll test;
std::cout << test.Add(2, 5) << std::endl;
test.myPrint("Func myPrint()");
printStr("Func printStr()");
printf("num = %d", num);
return 0;
}
3、项目属性中添加头文件路径

或者:将头文件拷贝至项目文件同一目录下,即项目默认的头文件搜索路径中。
4、项目属性中添加dll对应.lib路径

5、项目属性中附加依赖项里添加dll对应的.lib文件名

步骤4、5可使用以下代码替代。其中的路径可以使用相对路径(这里为绝对路径)。
#pragma comment (lib,"D:/Project Files/MyDll/Debug/MyDll.lib")
19.2 显式加载/隐式加载--《Windows核心编程》的更多相关文章
- selenium-webdriver中的显式等待与隐式等待
在selenium-webdriver中等待的方式简单可以概括为三种: 1 导入time包,调用time.sleep()的方法传入时间,这种方式也叫强制等待,固定死等一个时间 2 隐式等待,直接调用i ...
- 转】C#接口-显式接口和隐式接口的实现
[转]C#接口-显式接口和隐式接口的实现 C#中对于接口的实现方式有隐式接口和显式接口两种: 类和接口都能调用到,事实上这就是“隐式接口实现”. 那么“显示接口实现”是神马模样呢? interface ...
- C# Interface显式实现和隐式实现
c#中对接口的实现方式有两种:隐式实现和显式实现,之前一直没仔细看过,今天查了些资料,在这里整理一下. 隐式实现的例子 interface IChinese { string Speak(); } p ...
- 多态设计 zen of python poem 显式而非隐式 延迟赋值
总结 1.python支持延迟赋值,但是给调用者带来了困惑: 2.显式而非隐式,应当显式地指定要初始化的变量 class Card: def __init__(self, rank, suit): s ...
- C# 数据类型转换 显式转型、隐式转型、强制转型
C# 的类型转换有 显式转型 和 隐式转型 两种方式. 显式转型:有可能引发异常.精确度丢失及其他问题的转换方式.需要使用手段进行转换操作. 隐式转型:不会改变原有数据精确度.引发异常,不会发生任何问 ...
- (java)selenium webdriver学习---三种等待时间方法:显式等待,隐式等待,强制等待
selenium webdriver学习---三种等待时间方法:显式等待,隐式等待,强制等待 本例包括窗口最大化,刷新,切换到指定窗口,后退,前进,获取当前窗口url等操作: import java. ...
- Java并发之显式锁和隐式锁的区别
Java并发之显式锁和隐式锁的区别 在面试的过程中有可能会问到:在Java并发编程中,锁有两种实现:使用隐式锁和使用显示锁分别是什么?两者的区别是什么?所谓的显式锁和隐式锁的区别也就是说说Synchr ...
- Scala隐式转换和隐式参数
隐式转换 Scala提供的隐式转换和隐式参数功能,是非常有特色的功能.是Java等编程语言所没有的功能.它可以允许你手动指定,将某种类型的对象转换成其他类型的对象或者是给一个类增加方法.通过这些功能, ...
- Scala基础:闭包、柯里化、隐式转换和隐式参数
闭包,和js中的闭包一样,返回值依赖于声明在函数外部的一个或多个变量,那么这个函数就是闭包函数. val i: Int = 20 //函数func的方法体中使用了在func外部定义的变量 那func就 ...
- Scala 深入浅出实战经典 第61讲:Scala中隐式参数与隐式转换的联合使用实战详解及其在Spark中的应用源码解析
王家林亲授<DT大数据梦工厂>大数据实战视频 Scala 深入浅出实战经典(1-87讲)完整视频.PPT.代码下载: 百度云盘:http://pan.baidu.com/s/1c0noOt ...
随机推荐
- 13、SpringBoot-配置文件里密码加密
系列导航 springBoot项目打jar包 1.springboot工程新建(单模块) 2.springboot创建多模块工程 3.springboot连接数据库 4.SpringBoot连接数据库 ...
- map三层循环遍历,操作数据
let tempArr = this.oldCityList.map(item => { return { value: item.code, text: item.name, type: it ...
- 云网络智慧课堂-Qt程序代码开发规范
序言: 编程规范可以提升代码可读性,提高可维护性. 目录: 一.命名规范 二.内存管理规范 三.函数方法规范 四.控制语句规范 五.注释规范 六.排版规范 七.版本管理规范 八.界面编程 词义解释:强 ...
- 一文搞清楚Java中的方法、常量、变量、参数
写在开头 在上一篇文章:一文搞清楚Java中的包.类.接口 中我们讲了Java中的包.类和接口,今天继续将剩下的方法.常量.变量以及参数梳理完. Java中的变量与常量 在JVM的运转中,承载的是数据 ...
- Ubuntu Linux下的PDF阅读器推荐——Okular
安装方法 在Ubuntu下直接使用sudo apt-get install okular即可,如果中间遇到依赖项的问题,可以通过运行sudo apt --fix-broken install来自动修复 ...
- Laravel - Eloquent 更新数据
public function ormUpdate() { # 1.通过模型更新数据 /* $student = Student::find(14); ...
- [转帖]下载 SQL Server Management Studio (SSMS)
https://learn.microsoft.com/zh-CN/sql/ssms/download-sql-server-management-studio-ssms?view=sql-serve ...
- [转帖]ORACLE USERENV函数
https://www.cnblogs.com/youngerger/p/8862210.html ORACLE USERENV函数 USERENV返回关于当前会话的信息.此信息可以用于编写一个应用程 ...
- 【转帖】高性能异步io机制:io_uring
文章目录 1.性能测试 1.1.FIO 1.2.rust_echo_benc 2.io_uring 2.1.io_uring_setup 2.2.io_uring_enter 2.3.io_uring ...
- [转帖]linux求数组的交集,shell/bash 交集、并集、差集
方法一(直接用文件名):取两个文本文件的并集.交集.差集 并: sort -m 交: sort -m 差 file1 - file2: sort -m 方法二(用变量参数):取两个文本文件的并集.交集 ...