百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

C++基础语法梳理:Windows 的动态链接库

cac55 2024-09-20 13:02 16 浏览 0 评论



Windows 应用程序入口函数

GUI(Graphical User Interface)应用,链接器选项:/SUBSYSTEM:WINDOWS

CUI(Console User Interface)应用,链接器选项:/SUBSYSTEM:CONSOLE

_tWinMain 与 _tmain 函数声明

Int WINAPI _tWinMain(
    HINSTANCE hInstanceExe,
    HINSTANCE,
    PTSTR pszCmdLine,
    int nCmdShow);

int _tmain(
    int argc,
    TCHAR *argv[],
    TCHAR *envp[]);

Windows 的动态链接库(Dynamic-Link Library)

部分知识点来自《Windows 核心编程(第五版)》

用处

(1)扩展了应用程序的特性

(2)简化了项目管理

(3)有助于节省内存

(4)促进了资源的共享

(5)促进了本地化

(6)有助于解决平台间的差异

(7)可以用于特殊目的

注意

(1)创建 DLL,事实上是在创建可供一个可执行模块调用的函数

(2)当一个模块提供一个内存分配函数(malloc、new)的时候,它必须同时提供另一个内存释放函数(free、delete)

(3)在使用 C 和 C++ 混编的时候,要使用 extern "C" 修饰符

(4)一个 DLL 可以导出函数、变量(避免导出)、C++ 类(导出导入需要同编译器,否则避免导出)

(5)DLL 模块:cpp 文件中的 __declspec(dllexport) 写在 include 头文件之前

(6)调用 DLL 的可执行模块:cpp 文件的 __declspec(dllimport) 之前不应该定义 MYLIBAPI

加载 Windows 程序的搜索顺序

1、包含可执行文件的目录

2、Windows 的系统目录,可以通过 GetSystemDirectory 得到

3、16 位的系统目录,即 Windows 目录中的 System 子目录

4、Windows 目录,可以通过 GetWindowsDirectory 得到

5、进程的当前目录

6、PATH 环境变量中所列出的目录

DLL 入口函数

DllMain 函数

BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
    switch(fdwReason)
    {
    case DLL_PROCESS_ATTACH:
        // 第一次将一个DLL映射到进程地址空间时调用
        // The DLL is being mapped into the process' address space.
        break;
    case DLL_THREAD_ATTACH:
        // 当进程创建一个线程的时候,用于告诉DLL执行与线程相关的初始化(非主线程执行)
        // A thread is bing created.
        break;
    case DLL_THREAD_DETACH:
        // 系统调用 ExitThread 线程退出前,即将终止的线程通过告诉DLL执行与线程相关的清理
        // A thread is exiting cleanly.
        break;
    case DLL_PROCESS_DETACH:
        // 将一个DLL从进程的地址空间时调用
        // The DLL is being unmapped from the process' address space.
        break;
    }
    return (TRUE); // Used only for DLL_PROCESS_ATTACH
}

载入卸载库

LoadLibrary、LoadLibraryExA、LoadPackagedLibrary、FreeLibrary、FreeLibraryAndExitThread 函数声明

// 载入库
HMODULE WINAPI LoadLibrary(
  _In_ LPCTSTR lpFileName
);
HMODULE LoadLibraryExA(
  LPCSTR lpLibFileName,
  HANDLE hFile,
  DWORD  dwFlags
);
// 若要在通用 Windows 平台(UWP)应用中加载 Win32 DLL,需要调用 LoadPackagedLibrary,而不是 LoadLibrary 或 LoadLibraryEx
HMODULE LoadPackagedLibrary(
  LPCWSTR lpwLibFileName,
  DWORD   Reserved
);

// 卸载库
BOOL WINAPI FreeLibrary(
  _In_ HMODULE hModule
);
// 卸载库和退出线程
VOID WINAPI FreeLibraryAndExitThread(
  _In_ HMODULE hModule,
  _In_ DWORD   dwExitCode
);

显示地链接到导出符号

GetProcAddress 函数声明

FARPROC GetProcAddress(
  HMODULE hInstDll,
  PCSTR pszSymbolName  // 只能接受 ANSI 字符串,不能是 Unicode
);

DumpBin.exe 查看 DLL 信息

在 VS 的开发人员命令提示符 使用 DumpBin.exe 可查看 DLL 库的导出段(导出的变量、函数、类名的符号)、相对虚拟地址(RVA,relative virtual address)。如:

LoadLibrary 与 FreeLibrary 流程图

LoadLibrary 与 FreeLibrary 流程图

LoadLibrary

FreeLibrary

DLL 库的编写(导出一个 DLL 模块)

DLL 库的编写(导出一个 DLL 模块) DLL 头文件

// MyLib.h

#ifdef MYLIBAPI

// MYLIBAPI 应该在全部 DLL 源文件的 include "Mylib.h" 之前被定义
// 全部函数/变量正在被导出

#else

// 这个头文件被一个exe源代码模块包含,意味着全部函数/变量被导入
#define MYLIBAPI extern "C" __declspec(dllimport)

#endif

// 这里定义任何的数据结构和符号

// 定义导出的变量(避免导出变量)
MYLIBAPI int g_nResult;

// 定义导出函数原型
MYLIBAPI int Add(int nLeft, int nRight);

DLL 源文件

// MyLibFile1.cpp

// 包含标准Windows和C运行时头文件
#include <windows.h>

// DLL源码文件导出的函数和变量
#define MYLIBAPI extern "C" __declspec(dllexport)

// 包含导出的数据结构、符号、函数、变量
#include "MyLib.h"

// 将此DLL源代码文件的代码放在此处
int g_nResult;

int Add(int nLeft, int nRight)
{
    g_nResult = nLeft + nRight;
    return g_nResult;
}

DLL 库的使用(运行时动态链接 DLL)

DLL 库的使用(运行时动态链接 DLL)

// A simple program that uses LoadLibrary and 
// GetProcAddress to access myPuts from Myputs.dll. 
 
#include <windows.h> 
#include <stdio.h> 
 
typedef int (__cdecl *MYPROC)(LPWSTR); 
 
int main( void ) 
{ 
    HINSTANCE hinstLib; 
    MYPROC ProcAdd; 
    BOOL fFreeResult, fRunTimeLinkSuccess = FALSE; 
 
    // Get a handle to the DLL module.
 
    hinstLib = LoadLibrary(TEXT("MyPuts.dll")); 
 
    // If the handle is valid, try to get the function address.
 
    if (hinstLib != NULL) 
    { 
        ProcAdd = (MYPROC) GetProcAddress(hinstLib, "myPuts"); 
 
        // If the function address is valid, call the function.
 
        if (NULL != ProcAdd) 
        {
            fRunTimeLinkSuccess = TRUE;
            (ProcAdd) (L"Message sent to the DLL function\n"); 
        }
        // Free the DLL module.
 
        fFreeResult = FreeLibrary(hinstLib); 
    } 

    // If unable to call the DLL function, use an alternative.
    if (! fRunTimeLinkSuccess) 
        printf("Message printed from executable\n"); 

    return 0;
}

运行库(Runtime Library)

典型程序运行步骤

(1)操作系统创建进程,把控制权交给程序的入口(往往是运行库中的某个入口函数)

(2)入口函数对运行库和程序运行环境进行初始化(包括堆、I/O、线程、全局变量构造等等)。

(3)入口函数初始化后,调用 main 函数,正式开始执行程序主体部分。

(4)main 函数执行完毕后,返回到入口函数进行清理工作(包括全局变量析构、堆销毁、关闭I/O等),然后进行系统调用结束进程。

一个程序的 I/O 指代程序与外界的交互,包括文件、管程、网络、命令行、信号等。更广义地讲,I/O 指代操作系统理解为 “文件” 的事物。

glibc 入口

_start -> __libc_start_main -> exit -> _exit

其中 main(argc, argv, __environ) 函数在 __libc_start_main 里执行。

MSVC CRT 入口

int mainCRTStartup(void)

执行如下操作:

(1)初始化和 OS 版本有关的全局变量。

(2)初始化堆。

(3)初始化 I/O。

(4)获取命令行参数和环境变量。

(5)初始化 C 库的一些数据。

(6)调用 main 并记录返回值。

(7)检查错误并将 main 的返回值返回。

C 语言运行库(CRT)

大致包含如下功能:

启动与退出:包括入口函数及入口函数所依赖的其他函数等。

标准函数:有 C 语言标准规定的C语言标准库所拥有的函数实现。

I/O:I/O 功能的封装和实现。

堆:堆的封装和实现。

语言实现:语言中一些特殊功能的实现。

调试:实现调试功能的代码。

C语言标准库(ANSI C)

包含:

标准输入输出(stdio.h)

文件操作(stdio.h)

字符操作(ctype.h)

字符串操作(string.h)

数学函数(math.h)

资源管理(stdlib.h)

格式转换(stdlib.h)

时间/日期(time.h)

断言(assert.h)

各种类型上的常数(limits.h & float.h)

变长参数(stdarg.h)

非局部跳转(setjmp.h)


今天的分享就到这里了,大家要好好学C++哟~

写在最后:对于准备学习C/C++编程的小伙伴,如果你想更好的提升你的编程核心能力(内功)不妨从现在开始!

编程学习书籍分享:

编程学习视频分享:

整理分享(多年学习的源码、项目实战视频、项目笔记,基础入门教程)

欢迎转行和学习编程的伙伴,利用更多的资料学习成长比自己琢磨更快哦!

对于C/C++感兴趣可以关注小编在后台私信我:【编程交流】一起来学习哦!可以领取一些C/C++的项目学习视频资料哦!已经设置好了关键词自动回复,自动领取就好了!

相关推荐

无力吐槽的自动续费(你被自动续费困扰过吗?)

今天因为工作需要,需要在百度文库上下载一篇文章。没办法,确实需要也有必要,只能老老实实的按要求买了个VIP。过去在百度文库上有过类似经历,当时为了写论文买了一个月的VIP,后面也没有太注意,直到第二个...

百度文库推出“文源计划”创作者可一键认领文档

11月7日,百度文库发布了旨在保护创作者权益的“文源计划”。所谓“文源计划”,即为每一篇文档找到源头,让创作者享受更多的权益。据百度文库总经理李小婉介绍,文源计划分为三部分,分别是版权认证、版权扶持和...

有开放大学学号的同学,百度文库高校版可以用了。

还在网上找百度文库的下载方式,只要从身边的朋友在读开放大学的,那他(她)的学号就可以登陆到国家开放大学图书馆,还使用百度文库高校版来下载。与百度文库稍有不同,但足够使用了。现转国图链接如下:htt...

搜索资源方法推荐(搜索资源的方法)

今天msgbox就要教大家如何又快又准的搜到各类资源,第一点,排除干扰百度搜索出来啊经常前排展示它的产品以及百度文库,如何去除呢?很简单,后面输入空格减号百度文库,比如你搜高等数学百度文库很多,只要后...

一行代码搞定百度文库VIP功能(2021百度文库vip账号密码共享)

百度文库作为大家常用查资料找文档的平台,大多数文档我们都可以直接在百度文库找到,然而百度文库也有让人头痛的时候。好不容易找到一篇合适的文档,当你准备复制的时候他却提示你需要开通VIP才能复制~~~下载...

百度文库文档批量上传工具用户说明书

百度文库文档批量上传工具用户说明书1、软件主要功能1、批量上传文档到百度文库,支持上传到收费、VIP专享、优享以及共享。2、支持自动分类和自动获取标签3、支持多用户切换,一个账户传满可以切换到...

百度文库现在都看不到文档是否上传成功,要凉了吗?

打开知识店铺,百度文库文档里显示都是下载这一按键,上传的文档也看不到是否成功?咋情况,要取消了吗?没通过审核的也不让你删除,是几个意思,想通吃吗?现在百度上传文档也很费劲,有时弄了半天的资料上传审核过...

微信推广引流108式:利用百度文库长期分享软文引流

百度文库相对于百度知道、百度百科来说,操作上没那么多条条框框,规则上也相对好把握些。做一条百度知道所花费的精力一般都会比做一条百度文库的要多些,老马个人操作下来觉得百度文库更好把握。但见仁见智吧,今天...

职场“避雷”指南 百度文库推出标准化劳动合同范本

轰轰烈烈的毕业季结束了,众多应届生在经过了“职场海选”后,已正式成为职场生力军的一员。这一阶段,除了熟悉业务,签订劳动合同、了解职场福利也迅速被提上日程。而随着国人法律意识的增强,百度文库内《劳动合同...

《百度文库》:素材精选宝库(百度文库官网首页)

《百度文库》:独特功能助力选择高质量素材在当今信息爆炸的时代,如何高效地获取并利用有价值的素材成为了许多人面临的挑战。而《百度文库》作为百度公司推出的一款在线文档分享平台,凭借其丰富的资源、强大的功能...

深度整合和开放AI能力 百度文库和网盘推出内容操作系统「沧舟OS」

【TechWeb】4月25日消息,Create2025百度AI开发者大会上,百度文库和百度网盘推出全球首个内容操作系统——沧舟OS。基于沧舟OS,百度文库APP全新上线「GenFlow超能搭子」...

女子发现大二作业被百度文库要求付费下载,律师:平台侵权,应赔偿

近日,28岁的黎女士在百度百科搜索家乡的小地名时,发现了自己在大二完成的课题作业。她继续搜索,发现多个平台收录了该文,比如豆丁网和文档之家等,有的还设置了付费或积分下载。2月15日,九派新闻记者以用户...

2016杀入百度文库的新捷径,只有少数人才知道的喔

百度的产品在SEO优化中的分量真不用多说,其实很多人都像我一样一直在找捷径。但是我经常发现很多人都是在用死方法。比如发贴吧发帖而不知道去申请一个吧主,知道自问自答而不知道去申请一个合作资格。口碑和贴吧...

百度文库付费文档搜索方法(百度文库付费文档搜索方法有哪些)

一直以来,百度文库中无论是个人中心还是个人主页,都没有像淘宝一样的店内搜索功能,连最近新开的知识店铺也没有设计店内搜索功能,这无论是对上传用户还是下载用户都不方便,上传用户想要搜索自己的文档无法办到...

供读者免费使用!泰达图书馆机构版百度文库新年上新啦

在泰达图书馆读者使用百度文库数字资源不需要VIP,免-费-用!惊不惊喜?快来了解一下吧……新年伊始,为满足区域企业、高校、科研院所以及居民群众在教学、科研及学习过程中,对各类文献资源的需求,泰达图书馆...

取消回复欢迎 发表评论: