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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章