1.封装WinMain至动态链接库
1.封裝WinMain至動態鏈接庫
DND的前言:
??? DND是定位于Windows平臺的2d游戲引擎,使用C++和DirectX 11實現,編譯器使用vs2015。保留了一些3d功能,適合做一些pc上的高效率2d游戲。目前已經是第n遍重寫引擎代碼了(n>= 5),在這次重寫的機會,也以發博客的方式記錄自己的學習筆記,同時也希望我所分享的一些技術能幫助到大家。
? 本章前言:
??? 在windows編程下,一般項目以控制臺窗口、Windows窗口、動態鏈接庫、靜態鏈接庫四種形式為目標生成。DND引擎使用動態鏈接庫的方式生成,而使用DND引擎的程序直接建立Windows窗口(即入口函數為WinMain)。雖然可以選擇以main作為入口,但是一開始出現的控制臺窗口并不好處理掉(隱藏掉還是會閃一下,程序員們怎么能忍,一下格比就下去了)。所以比較好的方式是以WinMain作為入口,然后再建立Console窗口作為調試信息窗口(這個窗口可選是否建立,一般調試的時候建立,發布后肯定不需要建立了)。但是作為引擎必須將WinMain封裝起來,HGE引擎就沒有處理這一點,導致使用難度提高了不少:-),想想我大一的時候。
? 最終效果:
??? 用戶建立Win32項目之后,只需要如下使用便可實現程序入口:
//main.cpp
#include <DND.h>
DNDMain()
{
??? //主函數內容
}
//endmain.cpp
? 實現過程:
??? 由于使用鏈接庫的程序(后面稱為用戶程序)是Win32窗口程序,它需要查找WinMain函數符號作為函數入口。但我們將其放入了動態鏈接庫,如下面所示:
//WinMain的定義式,放在了DND的項目中
#include <windows.h>
int WINAPIWinMain(HINSTANCEhinstance, HINSTANCE,LPSTR, int)
{
//一些內容
}
//end
??? 所以我們需要導出函數符號,右鍵項目文件->添加新建項->代碼->模塊定義文件(.def)。在def文件中添加導出WinMain,內容如下所示:
//export.def
LIBRARY"DND"
EXPORTS
WinMain
//end export.def
??? 這樣入口就會從庫中的WinMain入口函數執行。但是為了WinMain函數執行我們形式入口函數,需要從用戶執行模塊取得形式入口函數指針。這里用到了GetProcAddress函數,WinMain函數內容如下:
int WINAPIWinMain(HINSTANCEhinstance, HINSTANCE,LPSTR, int)
{
??? void(*_func_dnd_main)(void);
??? //從執行模塊獲取_func_dnd_main函數
??? _func_dnd_main = (void(*)())GetProcAddress(hinstance,"_func_dnd_main");
??? if (!_func_dnd_main)
??? {
??????? //錯誤處理
??????? return 0;
??? }
??? //執行形式入口函數
??? _func_dnd_main();
??? return 0;
}
??? 注意,在這里這個函數名字叫_func_dnd_main,當然你也可以隨便寫,只要各處統一就行了。在執行形式入口函數之前或之后,還可以執行引擎相關的一些函數,保證在用戶的代碼執行之前或之后執行。
??? 接著,我們需要在用戶程序中實現這個_func_dnd_main函數的定義,也就是形式入口函數。像下面這樣:
extern "C"__declspec(dllexport)void _func_dnd_main()
{
}
??? 其中extern “C”讓函數名以C的方式編譯,__declspec(dllexport)使這個函數從用戶程序中導出。為了簡化寫法,再定義一個宏DNDMain:
#defineDNDMainextern"C"__declspec(dllexport)void _func_dnd_main
??? 這樣,形式入口函數的寫法就變成了最終效果中的寫法,用起來十分簡單。
? 示例:
??? 打上一個斷點,可以發現程序執行到了我們想執行的地方,并且整個程序也只有5行。眼花了,8行:-)。?
?
?
作者:略游
日期:17-05-20
QQ:1339484752
總結
以上是生活随笔為你收集整理的1.封装WinMain至动态链接库的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: GCC选项_-Wl,-soname
- 下一篇: 2.创建适合游戏的窗口和消息循环