首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

Windows DLL 開發全攻略:從最簡 Demo 到導出類/變量/重載函數的完整實踐

     編輯:關於C語言

前言

動態鏈接庫(DLL)是 Windows 平台代碼復用與模塊化的基石。本文基於 Visual Studio 2010,從零構建 DLL,逐步講解顯式/隱式調用、導出函數/類/變量、裝飾名處理、DEF 文件與 `__declspec` 對比,最終實現跨 DLL 的 C++ 類導出與客戶端調用。

1. 最簡單的 DLL:只需 DllMain

#include <objbase.h>
#include <iostream>
using namespace std;

BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, void* lpReserved) {
    static HANDLE g_hModule;
    switch (dwReason) {
        case DLL_PROCESS_ATTACH:
            cout << "Dll is attached!" << endl;
            g_hModule = (HINSTANCE)hModule;
            break;
        case DLL_PROCESS_DETACH:
            cout << "Dll is detached!" << endl;
            g_hModule = NULL;
            break;
    }
    return TRUE;
}

項目屬性 → 配置類型 選 **動態庫 (.dll)**。生成即得 DLL。

2. 顯式調用:LoadLibrary + GetProcAddress

客戶端動態加載 DLL,通過函數指針調用導出函數。適合非 C/C++ 語言調用或插件架構。

// 客戶端
typedef void (*DLL_FUNC)();
HINSTANCE hinst = LoadLibrary(L"dll_nolib.dll");
if (hinst) {
    DLL_FUNC pf = (DLL_FUNC)GetProcAddress(hinst, "FuncInDll");
    if (pf) pf();
}

3. 導出函數的兩種方式

方式一:DEF 文件(僅限 C 風格)

LIBRARY dll_def.dll
EXPORTS
    FuncInDll @1 PRIVATE

方式二:`__declspec(dllexport)`(推薦,支持 C++)

__declspec(dllexport) void FuncInDll();

⚠️ C++ 編譯器會修改函數名(Name Mangling),導致 `GetProcAddress` 需裝飾名。解決方案:加 `extern "C"` 強制 C 風格命名:

extern "C" __declspec(dllexport) void FuncInDll();

4. 隱式調用:.h + .lib + .dll,像調用系統 API 一樣簡單

DLL 端導出時生成同名 `.lib` 導入庫。客戶端:

#include "dll_withlibAndH.h"
#pragma comment(lib, "dll_withLibAndH.lib")
int main() { FuncInDll(); return 0; }

5. 進階:`dllexport` / `dllimport` 配對宏,實現頭文件共享

// dll2.h
#ifdef DLL_DLL2_EXPORTS
#define DLL_DLL2_API __declspec(dllexport)
#else
#define DLL_DLL2_API __declspec(dllimport)
#endif
DLL_DLL2_API void FuncInDll2(void);
DLL_DLL2_API void FuncInDll2(int); // 重載函數

DLL 端定義 `DLL_DLL2_EXPORTS` 宏,客戶端不定義,同一頭文件自動切換導出/導入聲明。完美支持 C++ 重載、類、全局變量導出。

6. 導出 C++ 類、全局變量、成員函數

class DLL_OBJECT_API CDll_Object {
public:
    CDll_Object(); void show();
};
DLL_OBJECT_API int g_nDll = 9;

客戶端直接 `CDll_Object obj; obj.show();` 及訪問 `g_nDll`,無縫體驗。

7. 核心經驗總結

  • **顯式 vs 隱式**:非 C/C++ 客戶端用顯式,其餘首選隱式;
  • **DEF vs `__declspec`**:後者功能更強,支持 C++ 特性,現代開發首選;
  • **`extern "C"`**:僅用於需 C 鏈接的場合,會禁用重載;
  • **本質認知**:DLL 是 C 級動態鏈接技術,C++ 跨 DLL 需同編譯器、同運行庫、同內存模型,否則請用 COM。
本文整理自 “三人乘虎” 博客,原文鏈接:https://darhx.blog.51cto.com/7920146/1298950
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved