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

VC++ DLL 編程深度解析(二):非 MFC DLL 導出函數聲明與三種調用方式

     編輯:VC 教學

本系列第二部分聚焦 非 MFC DLL (Non-MFC DLL):不依賴 MFC,導出標準 C 介面,可被任何語言調用。核心內容包括:導出函數聲明兩種方式(__declspec(dllexport) 與 .def 文件)、應用程式三種調用模式(隱式鏈接、顯式運行時鏈接、序號調用)。

最小化 DLL 專案創建

  1. File → New → Project → Win32 Dynamic-Link Library(非 MFC AppWizard)。
  2. 專案名 dllTest,選擇 A simple DLL project。

導出函數聲明:兩種等效方式

方式一:__declspec(dllexport) (推薦,直觀)

// lib.h
#ifndef LIB_H
#define LIB_H
extern "C" int __declspec(dllexport) add(int x, int y);
#endif

// lib.cpp
#include "lib.h"
int add(int x, int y) { return x + y; }

方式二:模塊定義文件 (.def)

; lib.def
LIBRARY dllTest
EXPORTS
    add @1
  • LIBRARY 指定 DLL 名稱(影響導入庫生成)。
  • EXPORTS 列出導出符號,@n 指定序號(序號調用更快、體積更小)。
  • 註釋以分號 ; 開頭,不可與語句同行。

應用程式三種調用模式

1. 隱式鏈接 (Load-Time Dynamic Linking) —— 最常用

  • 編譯時鏈接 dllTest.lib(導入庫)。
  • 運行時系統自動載入 DLL,無需代碼干預。
// dllCall.cpp
#include 
#include "..\dllTest\lib.h"  // 含 __declspec(dllimport) 聲明
#pragma comment(lib, "..\Debug\dllTest.lib")

int main() {
    printf("%d", add(2, 3)); // 直接調用
    return 0;
}

2. 顯式運行時鏈接 (Run-Time Dynamic Linking) —— 靈活、可延遲載入

#include 
#include 

typedef int (*LPADD)(int, int); // 函數指針類型

int main() {
    HINSTANCE hDll = LoadLibrary("dllTest.dll");
    if (!hDll) return 1;

    LPADD pAdd = (LPADD)GetProcAddress(hDll, "add"); // 或 GetProcAddress(hDll, (LPCSTR)1) 按序號
    if (pAdd) printf("%d", pAdd(2, 3));

    FreeLibrary(hDll);
    return 0;
}

優點:DLL 路徑可配置、缺失不會導致進程啟動失敗、支援插件熱插拔。

3. 序號調用

.def 中指定 add @1,調用時 GetProcAddress(hDll, (LPCSTR)1)。
優點:導出表更小、無符號名洩露、調用略快。
缺點:維護序號映射表麻煩、重構易出錯。

DLL 內部函數 vs 導出函數

  • 導出函數:聲明 __declspec(dllexport) 或列在 .def,供外部調用。
  • 內部函數:無導出聲明,僅在 DLL 內部文件間調用(需 static 或匿名命名空間限制作用域)。

調試與查看導出表

  • VC 自帶 Depends.exe (Dependency Walker) 打開 DLL,查看 Export Table:函數名、序號、地址、是否為轉發導出。
  • 調試:DLL 專案與調用專案同一 Workspace,調用專案設為啟動項,斷點 F11 進入 DLL。

總結:選擇建議

場景推薦方式
固定依賴、追求簡潔隱式鏈接 + __declspec(dllexport)
插件架構、可選功能、多版本共存顯式 LoadLibrary/GetProcAddress
極度敏感體積、導出函數固定少量.def + 序號調用

非 MFC DLL 是跨語言、跨編譯器二進制複用的基石,掌握三種調用模式與導出聲明細節,能應對從簡單工具庫到複雜插件系統的各種場景。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved