剖析插件技術(shù)
作者:太子
mailto: tablejiang@21cn.com
轉(zhuǎn)載請(qǐng)保證文檔的完整性。
很多人對(duì)插件技術(shù)很感興趣,這兩天我對(duì)播放器的插件技術(shù)的原理做了些研究,現(xiàn)在就把 一些心得寫出來(lái)。
插件原理就是通過(guò)統(tǒng)一的程序接口來(lái)調(diào)用不同的模塊,以實(shí)現(xiàn)不同功能的調(diào)用。用來(lái)擴(kuò)充 主程序的功能。
現(xiàn)在我們來(lái)談?wù)勊膶?shí)現(xiàn)。
插件技術(shù)的實(shí)現(xiàn),一般都是先定義好一個(gè)接口結(jié)構(gòu)。這個(gè)結(jié)構(gòu)包含了主程序要引用的接 口函數(shù)的指針。當(dāng)然,這些接口函數(shù)的格式必須是事先定義好了的。
而在插件Dll中一般只有一個(gè)導(dǎo)出函數(shù),利用這個(gè)導(dǎo)出函數(shù),我們可以得到接口結(jié)構(gòu)的指針。
這樣主程序就可以通過(guò)指針來(lái)使用插件模塊中的功能了。
舉個(gè)例子:
我們先定義好包含接口函數(shù)的結(jié)構(gòu):
typedef struct PlugInModule{ DWORD Ver ; //版本 char *Author ; //作者說(shuō)明 char *Description; //模塊說(shuō)明 BYTE *InputPointer; //輸入數(shù)據(jù) [in/out] DWORD dwSize ; //輸入數(shù)據(jù)的大小 [in] HWND hParentWnd ; //父窗口 [in] HINSTANCE hDllInst ; //Dll句柄 [in] void (*PlugIn_Config)( struct PlugInModule * pModule ) ; //設(shè)置函數(shù) void (*PlugIn_Init)( struct PlugInModule * pModule ) ; //初始化函數(shù) void (*PlugIn_Quit)( struct PlugInModule * pModule ) ; //退出函數(shù) void (*PlugIn_Run )( struct PlugInModule * pModule ) ; //執(zhí)行函數(shù) } PlugInModule ;
還有申明Dll的導(dǎo)出函數(shù):
typedef PlugInModule* (*GETPLUGINMODULE)();
這樣,我們就定義好了一個(gè)插件的接口。
在插件Dll中,可以這樣實(shí)現(xiàn)。
申明和定義接口函數(shù)。 //函數(shù)定義 void JhmDll_Config( struct PlugInModule * pModule ) ; //設(shè)置函數(shù) void JhmDll_Init( struct PlugInModule * pModule ) ; //初始化函數(shù) void JhmDll_Quit( struct PlugInModule * pModule ) ; //退出函數(shù) void JhmDll_Run( struct PlugInModule * pModule ) ; //執(zhí)行函數(shù)
//模塊函數(shù)實(shí)現(xiàn) void JhmDll_Config( struct PlugInModule * pModule ) { char szDisplay[260] ; sprintf( szDisplay , "%s , config 模塊" , pModule->Description ) ; MessageBox( NULL , "config" , pModule->Author , MB_OK ) ; }
void JhmDll_Init( struct PlugInModule * pModule ) { char szDisplay[260] ; sprintf( szDisplay , "%s , Init 模塊" , pModule->Description ) ; MessageBox( NULL , "Init" , pModule->Author , MB_OK ) ; }
void JhmDll_Quit( struct PlugInModule * pModule ) { char szDisplay[260] ; sprintf( szDisplay , "%s , Quit 模塊" , pModule->Description ) ; MessageBox( NULL , "Quit" , pModule->Author , MB_OK ) ; }
void JhmDll_Run( struct PlugInModule * pModule ) { char szDisplay[260] ; sprintf( szDisplay , "%s , Run 模塊" , pModule->Description ) ; MessageBox( NULL , "Run" , pModule->Author , MB_OK ) ; }
這樣,我們就定義好了接口函數(shù)。 當(dāng)然,我們必須把它們加入到接口結(jié)構(gòu)中去。
這樣,再定義一個(gè)接口結(jié)構(gòu),并同時(shí)初始化: //初始化接口 PlugInModule module = { 0x0100 , "Table.JHM.太子" , "示范插件技術(shù)1--空模塊" , NULL , 0 , NULL , NULL , JhmDll_Config , JhmDll_Init , JhmDll_Quit , JhmDll_Run , };
然后再定義Dll的導(dǎo)出函數(shù) //插件的接口 #ifdef __cplusplus extern "C" { #endif
__declspec( dllexport ) PlugInModule *GetPlugInModuleFunction() { return &module; }
#ifdef __cplusplus } #endif
這樣,一個(gè)插件dll的接口功能就完成了,當(dāng)然,你需要在接口函數(shù)中添加你的插件功能代碼。
這樣主程序再通過(guò)動(dòng)態(tài)加載Dll,映射導(dǎo)出函數(shù)地址, 就可以通過(guò)導(dǎo)出函數(shù) GetPlugInModuleFunction()得到一個(gè)PlugInModule結(jié)構(gòu)的指針。而PlugInMoudle包含插件功能 的功能函數(shù)地址,這樣就可以引用 void JhmDll_Config( struct PlugInModule * pModule ) ; //設(shè)置函數(shù) void JhmDll_Init( struct PlugInModule * pModule ) ; //初始化函數(shù) void JhmDll_Quit( struct PlugInModule * pModule ) ; //退出函數(shù) void JhmDll_Run( struct PlugInModule * pModule ) ; //執(zhí)行函數(shù) 這些插件函數(shù)的功能了。
這只是個(gè)人想法,如果有不同意見的可以 email 。歡迎討論。
如果需要更詳細(xì)的內(nèi)容,大家可以到http://wolfftp.51.net 或 http://mywolfsoft.51.net 去 下載示范源代碼。 |