部分笔记来自于: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核心编程》的更多相关文章

  1. selenium-webdriver中的显式等待与隐式等待

    在selenium-webdriver中等待的方式简单可以概括为三种: 1 导入time包,调用time.sleep()的方法传入时间,这种方式也叫强制等待,固定死等一个时间 2 隐式等待,直接调用i ...

  2. 转】C#接口-显式接口和隐式接口的实现

    [转]C#接口-显式接口和隐式接口的实现 C#中对于接口的实现方式有隐式接口和显式接口两种: 类和接口都能调用到,事实上这就是“隐式接口实现”. 那么“显示接口实现”是神马模样呢? interface ...

  3. C# Interface显式实现和隐式实现

    c#中对接口的实现方式有两种:隐式实现和显式实现,之前一直没仔细看过,今天查了些资料,在这里整理一下. 隐式实现的例子 interface IChinese { string Speak(); } p ...

  4. 多态设计 zen of python poem 显式而非隐式 延迟赋值

    总结 1.python支持延迟赋值,但是给调用者带来了困惑: 2.显式而非隐式,应当显式地指定要初始化的变量 class Card: def __init__(self, rank, suit): s ...

  5. C# 数据类型转换 显式转型、隐式转型、强制转型

    C# 的类型转换有 显式转型 和 隐式转型 两种方式. 显式转型:有可能引发异常.精确度丢失及其他问题的转换方式.需要使用手段进行转换操作. 隐式转型:不会改变原有数据精确度.引发异常,不会发生任何问 ...

  6. (java)selenium webdriver学习---三种等待时间方法:显式等待,隐式等待,强制等待

    selenium webdriver学习---三种等待时间方法:显式等待,隐式等待,强制等待 本例包括窗口最大化,刷新,切换到指定窗口,后退,前进,获取当前窗口url等操作: import java. ...

  7. Java并发之显式锁和隐式锁的区别

    Java并发之显式锁和隐式锁的区别 在面试的过程中有可能会问到:在Java并发编程中,锁有两种实现:使用隐式锁和使用显示锁分别是什么?两者的区别是什么?所谓的显式锁和隐式锁的区别也就是说说Synchr ...

  8. Scala隐式转换和隐式参数

    隐式转换 Scala提供的隐式转换和隐式参数功能,是非常有特色的功能.是Java等编程语言所没有的功能.它可以允许你手动指定,将某种类型的对象转换成其他类型的对象或者是给一个类增加方法.通过这些功能, ...

  9. Scala基础:闭包、柯里化、隐式转换和隐式参数

    闭包,和js中的闭包一样,返回值依赖于声明在函数外部的一个或多个变量,那么这个函数就是闭包函数. val i: Int = 20 //函数func的方法体中使用了在func外部定义的变量 那func就 ...

  10. Scala 深入浅出实战经典 第61讲:Scala中隐式参数与隐式转换的联合使用实战详解及其在Spark中的应用源码解析

    王家林亲授<DT大数据梦工厂>大数据实战视频 Scala 深入浅出实战经典(1-87讲)完整视频.PPT.代码下载: 百度云盘:http://pan.baidu.com/s/1c0noOt ...

随机推荐

  1. 13、SpringBoot-配置文件里密码加密

    系列导航 springBoot项目打jar包 1.springboot工程新建(单模块) 2.springboot创建多模块工程 3.springboot连接数据库 4.SpringBoot连接数据库 ...

  2. map三层循环遍历,操作数据

    let tempArr = this.oldCityList.map(item => { return { value: item.code, text: item.name, type: it ...

  3. 云网络智慧课堂-Qt程序代码开发规范

    序言: 编程规范可以提升代码可读性,提高可维护性. 目录: 一.命名规范 二.内存管理规范 三.函数方法规范 四.控制语句规范 五.注释规范 六.排版规范 七.版本管理规范 八.界面编程 词义解释:强 ...

  4. 一文搞清楚Java中的方法、常量、变量、参数

    写在开头 在上一篇文章:一文搞清楚Java中的包.类.接口 中我们讲了Java中的包.类和接口,今天继续将剩下的方法.常量.变量以及参数梳理完. Java中的变量与常量 在JVM的运转中,承载的是数据 ...

  5. Ubuntu Linux下的PDF阅读器推荐——Okular

    安装方法 在Ubuntu下直接使用sudo apt-get install okular即可,如果中间遇到依赖项的问题,可以通过运行sudo apt --fix-broken install来自动修复 ...

  6. Laravel - Eloquent 更新数据

    public function ormUpdate()     {         # 1.通过模型更新数据        /*  $student = Student::find(14);      ...

  7. [转帖]下载 SQL Server Management Studio (SSMS)

    https://learn.microsoft.com/zh-CN/sql/ssms/download-sql-server-management-studio-ssms?view=sql-serve ...

  8. [转帖]ORACLE USERENV函数

    https://www.cnblogs.com/youngerger/p/8862210.html ORACLE USERENV函数 USERENV返回关于当前会话的信息.此信息可以用于编写一个应用程 ...

  9. 【转帖】高性能异步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 ...

  10. [转帖]linux求数组的交集,shell/bash 交集、并集、差集

    方法一(直接用文件名):取两个文本文件的并集.交集.差集 并: sort -m 交: sort -m 差 file1 - file2: sort -m 方法二(用变量参数):取两个文本文件的并集.交集 ...