轉自:http://blog.csdn.net/songyi160/article/details/50754705
VS2015用C++創建動態庫DLL步驟如下:
(1)啟動VS2015》文件》新建》項目,按下圖進行選擇填寫,選擇Win32控制台應用程序或Win32項目都可以,這兩相都會彈出相同的創建窗口,如第二張圖,第三張圖。
(2)在Win32應用程序向導對話框中選擇【下一步】
(3)按下圖進行勾選
預編譯頭作用:VS 默認情況下會創建並使用預編譯頭文件(也就是自動創建 StdAfx.h 和 StdAfx.cpp 這兩個文件),以便在編譯時加快編譯速度,預編譯器將它編譯后,會生成一 個 Pre-compiled header ,也就是 pch 文件,這樣下次就可以直接使用這里已經編譯好了的代碼了。
(4)整個測試項目創建后,整體效果如下圖:
(5)在解決方案中找到【頭文件】然后右擊選擇【添加】》【新建項】,在彈出的添加新項對話框中進行如下選擇:
(6)打開DLLTest.cpp並添加如下圖紅色框中的函數test1和test2,同時將DLLTest.h頭文件包含進來,具體如下圖:
(7)打開DLLTest.h並添加函數test1和test2的導出形式,具體如下圖:
注意:__stdcall定義導出函數入口點調用約定為_stdcall
extern "C"說明導出函數使用C編譯器,則函數名遵循C編譯器的函數名修飾規則,不加extern "C"說明使用C++編譯器的函數名修飾 規則,兩種規則區別如下:
(1)C編譯器的函數名修飾規則
對於__stdcall調用約定,編譯器和鏈接器會在輸出函數名前加上一個下划線前綴,函數名后面加上一個“@”符號和其參數的字節數,例如 _functionname@number。__cdecl調用約定僅在輸出函數名前加上一個下划線前綴,例如_functionname。__fastcall調用約定在輸出函 數名前加上一個“@”符號,后面也是一個“@”符號和其參數的字節數,例如@functionname@number
(2)C++編譯器的函數名修飾規則
C++的函數名修飾規則有些復雜,但是信息更充分,通過分析修飾名不僅能夠知道函數的調用方式,返回值類型,甚至參數個數、參數類 型。不管__cdecl,__fastcall還是__stdcall調用方式,函數修飾都是以一個“?”開始,后面緊跟函數的名字,再后面是參數表的開始標識 和按照參數類型代號拼出的參數表。對於__stdcall方式,參數表的開始標識是“@@YG”,對於__cdecl方式則是“@@YA”,對於 __fastcall方式則是“@@YI”。參數的具體含義見上篇博客【VS2015用C++創建的動態庫導出函數名亂碼原因分析】。
(8)使用extern "C"導出的函數名,如圖一,不使用extern "C"導出的函數名,如圖二。
圖一
圖二
注意在圖二中如果看到的函數不是圖中所示,請在函數名上右擊去掉對【Undecorate C++ Functions】的選擇
(9)針對上面的敘述可以看出無論是添加extern "C"還是不添加,都不是我們想要的函數名,.h頭文件的作用僅僅能導出動態庫、明確編譯鏈接方式及確定入口點約定,還一個重要作用是打包給開發者,使其了解動態庫導出的函數及對應的的參數,為了確保導出函數名及入口點函數不變,此時需添加.def文件,步驟如下:
(10)在解決方案中找到【源文件】右擊選擇【添加】》【新建項】,在彈出的添加新項對話框中進行如下圖所示選擇:
(11)在DLLTest.def文件中寫入如下代碼:
使用def文件的意義:將編譯器生成的函數修飾去掉,用更加自然、更加容易理解、更加容易記憶的名字來命名函數,而不是一串人一看就嚇一跳的 修飾名字。
(12)在生成解決方案前先進行如下修改,CPU選X86還是X64隨便你啦
(13)請注意一定要是Release模式而不能是Debug模式,否則生成的動態庫DLL文件有可能還是不能被其他語言調用,原因現在還不清楚,有知道的朋友請留言,謝謝。為對比可查看Release文件夾和Debug文件夾中生成的動態庫DLL文件的大小也是不同的。
(14)用def文件導出的動態庫DLL既可以保證函數名不變也可以保證動態庫DLL的入口點函數名不變,同時在.cpp文件中函數定義中加入__stdcall就可以實現導出的DLL被其它語言調用,此時.h頭文件的作用僅僅打包給開發者,供其查看導出的函數名及相應參數而已。