0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

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

C语言编程学习基地 来源:C语言编程学习基地 作者: C语言编程 2021-11-02 09:21 次阅读

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[]);

4e0e46d2-3b52-11ec-82a9-dac502259ad0.png

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 或 LoadLibraryExHMODULE 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)。如:

DUMPBIN -exports D:mydll.dll

LoadLibrary 与 FreeLibrary 流程图

LoadLibrary 与 FreeLibrary 流程图

LoadLibrary

4e6d4092-3b52-11ec-82a9-dac502259ad0.png

FreeLibrary

4f09b3e6-3b52-11ec-82a9-dac502259ad0.png

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 
// 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  #include   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
");         }        // Free the DLL module.         fFreeResult = FreeLibrary(hinstLib);     } 
    // If unable to call the DLL function, use an alternative.    if (! fRunTimeLinkSuccess)         printf("Message printed from executable
"); 
    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)

编辑:jq
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • WINDOWS
    +关注

    关注

    3

    文章

    3515

    浏览量

    88285
  • 函数
    +关注

    关注

    3

    文章

    4273

    浏览量

    62302
  • C++
    C++
    +关注

    关注

    21

    文章

    2094

    浏览量

    73445
  • 动态链接库
    +关注

    关注

    0

    文章

    10

    浏览量

    7061

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

文章出处:【微信号:cyuyanxuexi,微信公众号:C语言编程学习基地】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    嵌入式学习-静态链接动态链接

    目标文件,一般是以.so文件形式存在。GCC默认是动态链接不需要加参数。举例子看一下动态链接库的使用方法,创建三个C语言文件:mymath.
    发表于 08-28 09:33

    静态链接动态链接

    目标文件,一般是以.so文件形式存在。GCC默认是动态链接不需要加参数。举例子看一下动态链接库的使用方法,创建三个C语言文件:mymath.
    发表于 08-27 10:20

    OpenHarmony标准系统C++公共基础类案例:HelloWorld

    1、程序简介该程序是基于凌蒙派OpenHarmony-v3.2.1标准系统C++公共基础类的简单案例:HelloWorld。主要讲解C++公共基础类案例如何搭建和编译。2、程序解析
    的头像 发表于 08-13 08:23 406次阅读
    OpenHarmony标准系统<b class='flag-5'>C++</b>公共基础类<b class='flag-5'>库</b>案例:HelloWorld

    c++编译后链接失败的原因?如何解决?

    /c++项目,将刚才新建的项目转换为c++项目。 完成后点击编译,此时也是正常的。 新建一个cpp文件,将原项目的main.c中内容全部拷贝到新建的cpp文件中保存,然后删除原main.c
    发表于 07-25 08:13

    C++中实现类似instanceof的方法

    函数,可实际上C++中没有。但是别着急,其实C++中有两种简单的方法可以实现类似Java中的instanceof的功能。 在 C++ 中,确定对象的类型是编程中实际需求,使开发人员能够做出
    的头像 发表于 07-18 10:16 480次阅读
    <b class='flag-5'>C++</b>中实现类似instanceof的方法

    ESP32+Eclipse如何添加C++生成的静态

    ESP32+Eclipse如何添加C++生成的静态
    发表于 06-21 08:20

    鸿蒙OS开发实例:【Native C++

    使用DevEco Studio创建一个Native C++应用。应用采用Native C++模板,实现使用NAPI调用C标准的功能。使用C
    的头像 发表于 04-14 11:43 2438次阅读
    鸿蒙OS开发实例:【Native <b class='flag-5'>C++</b>】

    两种linux系统下常见的HOOK方法

    Linux提供了一个名为LD_PRELOAD的环境变量。这个环境变量允许用户指定一个或多个共享链接库文件的路径。当程序启动时,动态加载器会在加载C语言运行库之前,首先加载LD_PRELOAD所指定的共享
    发表于 04-08 11:26 3781次阅读
    两种linux系统下常见的HOOK方法

    EtherCAT运动控制器在ROS上的应用开发案例(下)

    本篇文章我们主要介绍正运动技术动态链接库环境配置以及EtherCAT运动控制器在ROS下的单轴运动。
    的头像 发表于 03-17 11:11 813次阅读
    EtherCAT运动控制器在ROS上的应用开发案例(下)

    c语言,c++,java,python区别

    操作系统、嵌入式系统等对性能要求较高的场景。C语言的语法相对简单,学习曲线较平缓,也是学习其他高级语言的入门语言。 C++C++是在C
    的头像 发表于 02-05 14:11 1941次阅读

    vb语言和c++语言的区别

    Microsoft开发的一种面向对象的事件驱动编程语言。它的设计目标是简化编程过程,让初学者也能快速上手。与相比,C++语言是一种通用的、面向对象的编程语言,其设计目标是提供高性能的系统级编程。 语法: VB语言的
    的头像 发表于 02-01 10:20 1889次阅读

    C++简史:C++是如何开始的

    MISRA C++:2023,MISRA® C++ 标准的下一个版本,来了!为了帮助您做好准备,我们介绍了 Perforce 首席技术支持工程师 Frank van den Beuken 博士撰写
    的头像 发表于 01-11 09:00 507次阅读
    <b class='flag-5'>C++</b>简史:<b class='flag-5'>C++</b>是如何开始的

    LabVIEW程序中包含.net和C++dll的注意事项简介

    LabVIEW的VI调用.NET程序集或者C++动态链接库时的关系图如下
    的头像 发表于 12-11 09:22 1226次阅读
    LabVIEW程序中包含.net和<b class='flag-5'>C</b>++dll的注意事项简介

    OpenHarmony C++公共基础类应用案例:HelloWorld

    1、程序简介该程序是基于OpenHarmony的C++公共基础类的简单案例:HelloWorld。该应用案例已在OpenHarmony凌蒙派-RK3568开发板(即
    的头像 发表于 11-23 08:22 658次阅读
    OpenHarmony <b class='flag-5'>C++</b>公共基础类<b class='flag-5'>库</b>应用案例:HelloWorld

    OpenHarmony C++公共基础类应用案例:Thread

    1、程序简介该程序是基于OpenHarmony的C++公共基础类的线程处理:Thread。该应用案例已在OpenHarmony凌蒙派-RK3568开发板(即
    的头像 发表于 11-23 08:22 838次阅读
    OpenHarmony <b class='flag-5'>C++</b>公共基础类<b class='flag-5'>库</b>应用案例:Thread