MinGW(GCC)編譯DLL文件


這兩天用CB(Code::Blocks)寫個小程序,要編譯出DLL供VB(6)使用。CB使用mingw-gcc作為編譯器,在庫文件的產出上跟VC、VS之類的IDE略有不同。

由於C語言的基礎知識不是太好,尤其對編譯環節更是知之甚少。結果,試了幾次,導出的DLL中的函數總是無法被調用。

用VB加載時總是提示"DLL調用約定錯誤",百度之了解到VB只能調用適配__stdcall約定(這也是其他語言也能調用C的默認方式)的函數。

於是在源文件中的函數前加上__stdcall,導出后又提示"找不到DLL入口點foo in mydll.dll",搜索得知可能是導出函數的名字有問題。

打開DLL Export Viewer,載入mydll.dll,發現函數變成了"foo@4"。

網上的說法是使用__stdcall的副作用,可以用extern "C"來避免,於是又加上extern "C",結果依舊。

還有人說可以用DEF文件來控制導出的函數名,不過我也沒查到具體該怎么加入到編譯過程中。

不斷google&baidu之后,發現gcc可以在鏈接階段通過指定--kill-at參數來消除這種情況。於是,緊接着又了解了下gcc的使用方法,嘗試幾次后終於成功了。

在這不得不吐槽部分人寫的技術博客,很多問題就是只言片語帶過,讓人看得雲里霧里。我覺得人可以說錯話,但是起碼要把自己的意思表達清楚,不然胡亂湊出一篇誤人誤己。

 

這里編寫個簡單例子來說明下具體是如何操作的:

建立DLL項目,結構如下:

test/
----mydll.h
----mydll.c

 

頭文件:mydll.h

#ifndef __MYDLL_H__
#define __MYDLL_H__

#ifdef BUILD_DLL
    #define DLL_EXPORT __declspec(dllexport)
#else
    #define DLL_EXPORT __declspec(dllimport)
#endif

#ifdef __cplusplus
extern "C" {
#endif
    DLL_EXPORT int __stdcall foo(int x);
#ifdef __cplusplus
}
#endif

#endif // __MYDLL_H__

 

C文件:mydll.c

#include "mydll.h"

DLL_EXPORT int __stdcall foo(int x) {
    return x;
}

 

如果你安裝了Code::Blocks(和MinGW),那么創建環境變量:

MINGW_HOME="C:\Program Files\CodeBlocks\MinGW"
PATH=%MINGW_HOME%\bin;%PATH%

 

打開命令行,進入我們的項目路徑中:

d:\test>
#執行編譯命令
d:\test>mingw32-gcc -c -DBUILD_DLL mydll.c #執行鏈接命令,生成mydll.dll和靜態庫文件libmydll.a
d:\test>mingw32-gcc -shared -o mydll.dll mydll.o -Wl,--kill-at,--out-implib,libmydll.a
Creating library file: libmydll.a

以上,就是我們生成DLL的全過程了。

 

接下來,打開VB我們來驗證下:

Private Declare Function foo Lib "d:\test\mydll.dll" (ByVal x As Integer) As Integer

Private Sub Form_Load()
    Debug.Print foo(10)
End Sub

運行OK,立即窗口輸出10。

 

用Python測試下:

>>> import ctypes
>>> mydll = ctypes.windll.LoadLibrary("d:\\test\\mydll.dll")
>>> print mydll.foo(10)
10
>>> 

好,也沒問題,那么證明結果上是正確的。

當然,由於本人水平較低,文章中肯定有描述不正確的地方,各位大神如果如果看到還請不吝指教。

 

 

參考文檔:

http://baike.baidu.com/view/2814224.htm

http://baike.baidu.com/view/1276580.htm?fr=aladdin

http://blog.sina.com.cn/s/blog_4b02b8d001000avi.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM