全方位解讀DLL檔案—編寫DLL

weixin_33850890發表於2018-10-12

前情提要

dll 的編寫特別要注意你的編譯器選擇,我目前也只用了兩個主流的編譯器做過測試,一個是微軟 VisualStudio 自帶的 MSVC編譯器,另一個是 GNU 在 Windows 上的 MinGW編譯器
如果你使用 MinGW,那麼和寫普通程式區別不大;但如果你使用 MSVC 的話,你就需要注意一些固定的格式,以及一些巨集定義

MSVC版

直接新建一個 dll 檔案專案,先寫一個標頭檔案,把一些變數和函式的定義寫好,這裡有興趣的話可以瞭解一下 #ifdef 以及 extern "C" __declspec(dllimport),標頭檔案 header.h 程式碼如下

#ifdef MYLIBAPI
#define MYLIBAPI extern "C" __declspec(dllexport)
#else
#define MYLIBAPI extern "C" __declspec(dllimport)
#endif
MYLIBAPI int res;
MYLIBAPI int myadd(int num1,int num2);

然後是主要的功能程式碼,mydll.c 程式碼如下

#include <windows.h>
#define MYLIBAPI extern "C" __declspec(dllimport)
#include "header.h"
int res;

int myadd(int num1,int num2){
    res = num1 + num2;
    return res;
}

注意事項:
extern "C" 主要是排除 C++ 編譯的干擾,C++ 編譯某個函式後會變成 func@ 的形式,不方便主程式根據函式名呼叫
__declspec(dllimport) 從其它動態庫中宣告匯入函式、類、物件等供本動態庫或exe檔案使用,在沒有全域性靜態變數時可以不使用該關鍵字
__declspec(dllexport) 宣告為匯出函式、類、物件等供其它程式呼叫,如果不使用該關鍵字匯出 dll 函式,則需要 .def 檔案

MinGW版

使用 MinGW 編譯器的話和寫普通程式類似,只寫需要用到的函式即可,不需要 main 主函式,然後編譯成 dll 檔案即可。編譯一句搞定 gcc math.c -shared -o math.dll -Wl,--out-implib,math.lib,--output-def,math.def,還能生成 .lib 以及 .def 檔案,用 C++ 的話可能還需要 --kill-at,mydll.c 程式碼如下:

#include<stdio.h>
int add(int a,int b){
    return a+b;
}
int sub(int a,int b){
    return a-b;
}
int mul(int a,int b){
    return a*b;
}
int div(int a,int b){
    return a/b;
}
// gcc math.c -shared -o math.dll -Wl,--out-implib,math.lib,--output-def,math.def

注意: dll 程式其實也是有入口函式的-DllMain,作業系統在呼叫 LoadLibrary() 執行緒的上下文中呼叫此入口函式,並且入口函式中通常會說明該 dll 被呼叫的方式!除非有特殊需求,一般不需要寫 DllMain 函式

END

相關文章