衡阳派盒市场营销有限公司

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

C++基礎(chǔ)語法梳理之Windows 的動態(tài)鏈接庫

C語言編程學(xué)習(xí)基地 ? 來源:C語言編程學(xué)習(xí)基地 ? 作者: C語言編程 ? 2021-11-02 09:21 ? 次閱讀

Windows 應(yīng)用程序入口函數(shù)

GUI(Graphical User Interface)應(yīng)用,鏈接器選項:/SUBSYSTEM:WINDOWS

CUI(Console User Interface)應(yīng)用,鏈接器選項:/SUBSYSTEM:CONSOLE

_tWinMain 與 _tmain 函數(shù)聲明

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 的動態(tài)鏈接庫(Dynamic-Link Library)

部分知識點來自《Windows 核心編程(第五版)》

用處

(1)擴(kuò)展了應(yīng)用程序的特性

(2)簡化了項目管理

(3)有助于節(jié)省內(nèi)存

(4)促進(jìn)了資源的共享

(5)促進(jìn)了本地化

(6)有助于解決平臺間的差異

(7)可以用于特殊目的

注意

(1)創(chuàng)建 DLL,事實上是在創(chuàng)建可供一個可執(zhí)行模塊調(diào)用的函數(shù)

(2)當(dāng)一個模塊提供一個內(nèi)存分配函數(shù)(malloc、new)的時候,它必須同時提供另一個內(nèi)存釋放函數(shù)(free、delete

(3)在使用 C 和 C++ 混編的時候,要使用 extern "C" 修飾符

(4)一個 DLL 可以導(dǎo)出函數(shù)、變量(避免導(dǎo)出)、C++ 類(導(dǎo)出導(dǎo)入需要同編譯器,否則避免導(dǎo)出)

(5)DLL 模塊:cpp 文件中的 __declspec(dllexport) 寫在 include 頭文件之前

(6)調(diào)用 DLL 的可執(zhí)行模塊:cpp 文件的 __declspec(dllimport) 之前不應(yīng)該定義 MYLIBAPI

加載 Windows 程序的搜索順序

1、包含可執(zhí)行文件的目錄

2、Windows 的系統(tǒng)目錄,可以通過 GetSystemDirectory 得到

3、16 位的系統(tǒng)目錄,即 Windows 目錄中的 System 子目錄

4、Windows 目錄,可以通過 GetWindowsDirectory 得到

5、進(jìn)程的當(dāng)前目錄

6、PATH 環(huán)境變量中所列出的目錄

DLL 入口函數(shù)

DllMain 函數(shù)

BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved){    switch(fdwReason)    {    case DLL_PROCESS_ATTACH:        // 第一次將一個DLL映射到進(jìn)程地址空間時調(diào)用        // The DLL is being mapped into the process' address space.        break;    case DLL_THREAD_ATTACH:        // 當(dāng)進(jìn)程創(chuàng)建一個線程的時候,用于告訴DLL執(zhí)行與線程相關(guān)的初始化(非主線程執(zhí)行)        // A thread is bing created.        break;    case DLL_THREAD_DETACH:        // 系統(tǒng)調(diào)用 ExitThread 線程退出前,即將終止的線程通過告訴DLL執(zhí)行與線程相關(guān)的清理        // A thread is exiting cleanly.        break;    case DLL_PROCESS_DETACH:        // 將一個DLL從進(jìn)程的地址空間時調(diào)用        // The DLL is being unmapped from the process' address space.        break;    }    return (TRUE); // Used only for DLL_PROCESS_ATTACH}

載入卸載庫

LoadLibrary、LoadLibraryExA、LoadPackagedLibrary、FreeLibrary、FreeLibraryAndExitThread 函數(shù)聲明

// 載入庫HMODULE WINAPI LoadLibrary(  _In_ LPCTSTR lpFileName);HMODULE LoadLibraryExA(  LPCSTR lpLibFileName,  HANDLE hFile,  DWORD  dwFlags);// 若要在通用 Windows 平臺(UWP)應(yīng)用中加載 Win32 DLL,需要調(diào)用 LoadPackagedLibrary,而不是 LoadLibrary 或 LoadLibraryExHMODULE LoadPackagedLibrary(  LPCWSTR lpwLibFileName,  DWORD   Reserved);
// 卸載庫BOOL WINAPI FreeLibrary(  _In_ HMODULE hModule);// 卸載庫和退出線程VOID WINAPI FreeLibraryAndExitThread(  _In_ HMODULE hModule,  _In_ DWORD   dwExitCode);

顯示地鏈接到導(dǎo)出符號

GetProcAddress 函數(shù)聲明

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

DumpBin.exe 查看 DLL 信息

在 VS 的開發(fā)人員命令提示符使用 DumpBin.exe 可查看 DLL 庫的導(dǎo)出段(導(dǎo)出的變量、函數(shù)、類名的符號)、相對虛擬地址(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 庫的編寫(導(dǎo)出一個 DLL 模塊)

DLL 庫的編寫(導(dǎo)出一個 DLL 模塊) DLL 頭文件

// MyLib.h
#ifdef MYLIBAPI
// MYLIBAPI 應(yīng)該在全部 DLL 源文件的 include "Mylib.h" 之前被定義// 全部函數(shù)/變量正在被導(dǎo)出
#else
// 這個頭文件被一個exe源代碼模塊包含,意味著全部函數(shù)/變量被導(dǎo)入#define MYLIBAPI extern "C" __declspec(dllimport)
#endif
// 這里定義任何的數(shù)據(jù)結(jié)構(gòu)和符號
// 定義導(dǎo)出的變量(避免導(dǎo)出變量)MYLIBAPI int g_nResult;
// 定義導(dǎo)出函數(shù)原型MYLIBAPI int Add(int nLeft, int nRight);

DLL 源文件

// MyLibFile1.cpp
// 包含標(biāo)準(zhǔn)Windows和C運行時頭文件#include 
// DLL源碼文件導(dǎo)出的函數(shù)和變量#define MYLIBAPI extern "C" __declspec(dllexport)
// 包含導(dǎo)出的數(shù)據(jù)結(jié)構(gòu)、符號、函數(shù)、變量#include "MyLib.h"
// 將此DLL源代碼文件的代碼放在此處int g_nResult;
int Add(int nLeft, int nRight){    g_nResult = nLeft + nRight;    return g_nResult;}

DLL 庫的使用(運行時動態(tài)鏈接 DLL)

DLL 庫的使用(運行時動態(tài)鏈接 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)操作系統(tǒng)創(chuàng)建進(jìn)程,把控制權(quán)交給程序的入口(往往是運行庫中的某個入口函數(shù))

(2)入口函數(shù)對運行庫和程序運行環(huán)境進(jìn)行初始化(包括堆、I/O、線程、全局變量構(gòu)造等等)。

(3)入口函數(shù)初始化后,調(diào)用 main 函數(shù),正式開始執(zhí)行程序主體部分。

(4)main 函數(shù)執(zhí)行完畢后,返回到入口函數(shù)進(jìn)行清理工作(包括全局變量析構(gòu)、堆銷毀、關(guān)閉I/O等),然后進(jìn)行系統(tǒng)調(diào)用結(jié)束進(jìn)程。

一個程序的 I/O 指代程序與外界的交互,包括文件、管程、網(wǎng)絡(luò)、命令行、信號等。更廣義地講,I/O 指代操作系統(tǒng)理解為 “文件” 的事物。

glibc 入口

_start -> __libc_start_main -> exit -> _exit

其中 main(argc, argv, __environ)函數(shù)在__libc_start_main 里執(zhí)行。

MSVC CRT 入口

int mainCRTStartup(void)

執(zhí)行如下操作:

(1)初始化和 OS 版本有關(guān)的全局變量。

(2)初始化堆。

(3)初始化 I/O。

(4)獲取命令行參數(shù)和環(huán)境變量。

(5)初始化 C 庫的一些數(shù)據(jù)。

(6)調(diào)用 main 并記錄返回值。

(7)檢查錯誤并將 main 的返回值返回。

C 語言運行庫(CRT)

大致包含如下功能:

啟動與退出:包括入口函數(shù)及入口函數(shù)所依賴的其他函數(shù)等。

標(biāo)準(zhǔn)函數(shù):有 C 語言標(biāo)準(zhǔn)規(guī)定的C語言標(biāo)準(zhǔn)庫所擁有的函數(shù)實現(xiàn)。

I/O:I/O 功能的封裝和實現(xiàn)。

堆:堆的封裝和實現(xiàn)。

語言實現(xiàn):語言中一些特殊功能的實現(xiàn)。

調(diào)試:實現(xiàn)調(diào)試功能的代碼。

C語言標(biāo)準(zhǔn)庫(ANSI C)

包含:

標(biāo)準(zhǔn)輸入輸出(stdio.h)

文件操作(stdio.h)

字符操作(ctype.h)

字符串操作(string.h)

數(shù)學(xué)函數(shù)(math.h)

資源管理(stdlib.h)

格式轉(zhuǎn)換(stdlib.h)

時間/日期(time.h)

斷言(assert.h)

各種類型上的常數(shù)(limits.h & float.h)

變長參數(shù)(stdarg.h)

非局部跳轉(zhuǎn)(setjmp.h)

編輯:jq
聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • WINDOWS
    +關(guān)注

    關(guān)注

    4

    文章

    3570

    瀏覽量

    89308
  • 函數(shù)
    +關(guān)注

    關(guān)注

    3

    文章

    4346

    瀏覽量

    62978
  • C++
    C++
    +關(guān)注

    關(guān)注

    22

    文章

    2114

    瀏覽量

    73859
  • 動態(tài)鏈接庫
    +關(guān)注

    關(guān)注

    0

    文章

    11

    瀏覽量

    7077

原文標(biāo)題:C++基礎(chǔ)語法梳理:Windows 的動態(tài)鏈接庫

文章出處:【微信號:cyuyanxuexi,微信公眾號:C語言編程學(xué)習(xí)基地】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    從Delphi、C++ Builder和Lazarus連接到MySQL數(shù)據(jù)

    ? 從 Delphi、C++ Builder 和 Lazarus 連接到 MySQL 數(shù)據(jù) MySQL 數(shù)據(jù)訪問組件(MyDAC)是一個組件,提供從 Delphi 和 C++ Bu
    的頭像 發(fā)表于 01-20 13:47 ?122次閱讀
    從Delphi、<b class='flag-5'>C++</b> Builder和Lazarus連接到MySQL數(shù)據(jù)<b class='flag-5'>庫</b>

    從Delphi、C++ Builder和Lazarus連接到Oracle數(shù)據(jù)

    C++ Builder(包括社區(qū)版),以及 Windows、Linux、macOS、iOS 和 Android 上的 Lazarus/Pascal,到 Oracle 的本機(jī)連接。ODAC 旨在
    的頭像 發(fā)表于 01-15 10:01 ?140次閱讀

    AKI跨語言調(diào)用神助攻C/C++代碼遷移至HarmonyOS NEXT

    )開發(fā)框架。它極大地簡化了JS與C/C++之間的跨語言訪問,為開發(fā)者提供了一種邊界性編程體驗友好的解決方案。通過AKI,開發(fā)者可以使用讓代碼更易讀的語法糖,實現(xiàn)JS與C/
    發(fā)表于 01-02 17:08

    深入探討Linux系統(tǒng)中的動態(tài)鏈接庫機(jī)制

    本文將深入探討Linux系統(tǒng)中的動態(tài)鏈接庫機(jī)制,這其中包括但不限于全局符號介入、延遲綁定以及地址無關(guān)代碼等內(nèi)容。 引言 在軟件開發(fā)過程中,動態(tài)鏈接
    的頭像 發(fā)表于 12-18 10:06 ?192次閱讀
    深入探討Linux系統(tǒng)中的<b class='flag-5'>動態(tài)</b><b class='flag-5'>鏈接庫</b>機(jī)制

    安卓動態(tài)鏈接庫文件體積優(yōu)化探索實踐

    諸多方面影響,針對dex、資源文件、so文件都有不同的優(yōu)化策略,在此不做一一展開,本文主要記錄了在研發(fā)時針對動態(tài)鏈接庫的文件體積裁剪優(yōu)化方案。 我開發(fā)的鏈接庫使用rust語言開發(fā),通過安卓jni接口實現(xiàn)java層和native層
    的頭像 發(fā)表于 11-21 14:07 ?187次閱讀

    嵌入式學(xué)習(xí)-靜態(tài)鏈接動態(tài)鏈接

    目標(biāo)文件,一般是以.so文件形式存在。GCC默認(rèn)是動態(tài)鏈接不需要加參數(shù)。舉例子看一下動態(tài)鏈接庫的使用方法,創(chuàng)建三個C語言文件:mymath.
    發(fā)表于 08-28 09:33

    靜態(tài)鏈接動態(tài)鏈接

    目標(biāo)文件,一般是以.so文件形式存在。GCC默認(rèn)是動態(tài)鏈接不需要加參數(shù)。舉例子看一下動態(tài)鏈接庫的使用方法,創(chuàng)建三個C語言文件:mymath.
    發(fā)表于 08-27 10:20

    OpenHarmony標(biāo)準(zhǔn)系統(tǒng)C++公共基礎(chǔ)類案例:HelloWorld

    1、程序簡介該程序是基于凌蒙派OpenHarmony-v3.2.1標(biāo)準(zhǔn)系統(tǒng)C++公共基礎(chǔ)類的簡單案例:HelloWorld。主要講解C++公共基礎(chǔ)類案例如何搭建和編譯。2、程序解析
    的頭像 發(fā)表于 08-13 08:23 ?579次閱讀
    OpenHarmony標(biāo)準(zhǔn)系統(tǒng)<b class='flag-5'>C++</b>公共基礎(chǔ)類<b class='flag-5'>庫</b>案例:HelloWorld

    c++編譯后鏈接失敗的原因?如何解決?

    /c++項目,將剛才新建的項目轉(zhuǎn)換為c++項目。 完成后點擊編譯,此時也是正常的。 新建一個cpp文件,將原項目的main.c中內(nèi)容全部拷貝到新建的cpp文件中保存,然后刪除原main.c
    發(fā)表于 07-25 08:13

    C++中實現(xiàn)類似instanceof的方法

    函數(shù),可實際上C++中沒有。但是別著急,其實C++中有兩種簡單的方法可以實現(xiàn)類似Java中的instanceof的功能。 在 C++ 中,確定對象的類型是編程中實際需求,使開發(fā)人員能夠做出
    的頭像 發(fā)表于 07-18 10:16 ?673次閱讀
    <b class='flag-5'>C++</b>中實現(xiàn)類似instanceof的方法

    ESP32+Eclipse如何添加C++生成的靜態(tài)

    ESP32+Eclipse如何添加C++生成的靜態(tài)?
    發(fā)表于 06-21 08:20

    鴻蒙OS開發(fā)實例:【Native C++

    使用DevEco Studio創(chuàng)建一個Native C++應(yīng)用。應(yīng)用采用Native C++模板,實現(xiàn)使用NAPI調(diào)用C標(biāo)準(zhǔn)的功能。使用C
    的頭像 發(fā)表于 04-14 11:43 ?2766次閱讀
    鴻蒙OS開發(fā)實例:【Native <b class='flag-5'>C++</b>】

    兩種linux系統(tǒng)下常見的HOOK方法

    Linux提供了一個名為LD_PRELOAD的環(huán)境變量。這個環(huán)境變量允許用戶指定一個或多個共享鏈接庫文件的路徑。當(dāng)程序啟動時,動態(tài)加載器會在加載C語言運行庫之前,首先加載LD_PRELOAD所指定的共享
    發(fā)表于 04-08 11:26 ?4426次閱讀
    兩種linux系統(tǒng)下常見的HOOK方法

    EtherCAT運動控制器在ROS上的應(yīng)用開發(fā)案例(下)

    本篇文章我們主要介紹正運動技術(shù)動態(tài)鏈接庫環(huán)境配置以及EtherCAT運動控制器在ROS下的單軸運動。
    的頭像 發(fā)表于 03-17 11:11 ?1028次閱讀
    EtherCAT運動控制器在ROS上的應(yīng)用開發(fā)案例(下)

    EtherCAT運動控制器在ROS上的應(yīng)用(下)

    正運動技術(shù)動態(tài)鏈接庫環(huán)境配置以及EtherCAT運動控制器在ROS下的單軸運動。
    的頭像 發(fā)表于 03-13 14:54 ?682次閱讀
    EtherCAT運動控制器在ROS上的應(yīng)用(下)
    澳门百家乐官网有赢钱的吗 | 百家乐官网三多注码法| 做生意适合放什么花招财| 百家乐合理的投注法| 鸿胜国际| 免费百家乐官网统计工具| 德州扑克看牌器| 24山安葬吉凶择日| 盐亭县| 百家乐看图赢| 百家乐官网开户送彩金28| 威尼斯人娱乐城评价| 博必发百家乐官网的玩法技巧和规则 | 明升国际| 二八杠的玩法| 百家乐2号干扰| 佳木斯市| 做生意的人早晨讲究| 百家乐官网www| 百家乐赢钱的技巧是什么| 网上百家乐哪里| 百家乐官网电投网址| 太阳城黑胶三折| 大赢家百家乐66| 娱网百家乐官网补丁| 鸿博娱乐| LV百家乐赢钱LV| 七乐百家乐现金网| 捷豹百家乐官网娱乐城| 百家乐官网的方法和公式| 云鼎娱乐城怎么存钱| 百家乐二路珠无敌稳赢打法| 百家乐玩法教学视频| 百家乐官网博彩的玩法技巧和规则 | 百家乐官网真人游戏攻略| 娱乐城简介| 大发888出纳柜台登入| 澳门百家乐现场真人版| 百家乐官网可以破解吗| 百家乐官网黄金城游戏大厅| 百家乐官网捡揽方法|