問題貼:[url]
[quote]1. 現有乙個主程式用c語言寫成。現在要允許第三方開發人員編寫擴充套件的模組,約定第三方開發的模組必須提供一系列已知名稱的函式(如 foo(),bar(),baz())。如果要求第三方的模組必須與主程式的二進位制**分開發布,把dll或so丟在某個資料夾內即可被動態裝載並使用,應如何實現?
[/quote]
回答:作業系統提供了shared object的動態裝載功能。定義在dlfcn.h中。呼叫dlopen()開啟外掛程式,dlsym()獲取函式,dlclose()關閉外掛程式。
適用於:
*nix。在linux中實驗成功。
實現:我們假定每個外掛程式提供兩個函式:
void hello(void); // 顯示hello world
void greet(char* name); // 給你打招呼
為了簡化裝載,我們用乙個struct儲存以上兩個函式的指標,並要求每個外掛程式內提供乙個叫init_module的函式,填充該struct。
介面標頭檔案如下:
/* plugin-inte***ce.h */
#ifndef _plugin_inte***ce_h_
#define _plugin_inte***ce_h_
#ifdef __cplusplus
extern "c" plugininte***ce;
typedef void (*initmodulefunc)(plugininte***ce* iface); // 這個函式填充上述結構。
#ifdef __cplusplus
}#endif
#endif
/* end of plugin-inte***ce.h */
總體的目錄結構如下:
[quote].
|-- makefile
|-- main
|-- main.c
|-- plugin-inte***ce.h
`-- plugins
|-- makefile
|-- goodbyeworld.c
|-- goodbyeworld.o
|-- goodbyeworld.so
|-- helloworld.c
|-- helloworld.o
`-- helloworld.so[/quote]
plugins裡的.so將被主程式main裝載。
看看plugins/helloworld.c:
/* plugins/helloworld.c */
#include
#include "../plugin-inte***ce.h"
// 兩個功能函式hello, greet的名稱隨便。我們只關心它們的指標。
void hw_hello()
void hw_greet(char* name)
// 填充plugininte***ce結構。
void init_module(plugininte***ce *iface)
/* end of plugins/helloworld.c */
plugins/goodbyeworld.c是另乙個外掛程式
/* plugins/goodbyeworld.c */
#include
#include "../plugin-inte***ce.h"
void gw_hello()
void gw_greet(char* name)
void init_module(plugininte***ce *iface)
/* end of plugins/goodbyeworld.c */
最後,main.c是主程式。
/* main.c */
#include
#include
#include
#include // dlopen(), dlsym(), dlclose()
#include
#include
#include "plugin-inte***ce.h"
#define max_plugins 10
char plugins_path = "plugins";
struct plugins[max_plugins]; // 每個struct對應乙個外掛程式
int n_plugins;
void load_plugin(char* path)
init_func = dlsym(lib_handle, "init_module"); // 找到init_module函式。
err = dlerror();
if(err != null)
strcpy(plugins[n_plugins].path,path);
plugins[n_plugins].lib_handle=lib_handle;
init_func(&plugins[n_plugins].iface); // 利用外掛程式中的"init_module"函式,填充iface結構
n_plugins++;
fprintf(stderr,"plugin successfully loaded: %s\n",path);
}int main()
while((dent=readdir(dir))!=null)
closedir(dir);
// 測試每個外掛程式
for(i=0;i// 解除安裝
for(i=0;ireturn 0;
}/* end of main.c */
編譯:
# makefile
all: main
main: main.c plugin-inte***ce.h
gcc -rdynamic -ldl -o $@ $^
# end of makefile
main.c的dlopen()等函式需要-ldl選項。-rdynamic選項也是dlopen()等函式需要的。
# plugins/makefile
all: helloworld.so goodbyeworld.so
helloworld.so: helloworld.c
gcc -c -fpic helloworld.c
gcc -shared -o helloworld.so helloworld.o
goodbyeworld.so: goodbyeworld.c
gcc -c -fpic goodbyeworld.c
gcc -shared -o goodbyeworld.so goodbyeworld.o
# end of plugins/makefile
這些是外掛程式的編譯方法。-fpic是構造so的必要條件。
另乙個選項是-wl,-soname,******x.so.x,這對動態鏈結(靜態裝載)有用,但是不加這個選項仍然可以動態裝載。
執行時,需要的最少的目錄結構如下:
[quote].
|-- main
`-- plugins
|-- goodbyeworld.so
`-- helloworld.so
[/quote]
執行:[quote][wks@localhost out]$ ./main
plugin successfully loaded: plugins/goodbyeworld.so
plugin successfully loaded: plugins/helloworld.so
testing plugins/goodbyeworld.so ...
goodbye world!
goodbye, wks
testing plugins/helloworld.so ...
hello world!
hello, wks
[/quote]
總結:1. main程式並不了解plugins目錄中有多少外掛程式。在執行時列舉目錄。
2. main程式對每個plugins檔案(比如叫helloworld.so)的了解只有:
- helloworld.so中有乙個函式叫init_module,可以填充plugininte***ce結構。
- helloworld.so將實現hello和greet兩個函式,但函式名可以不知道。函式指標被init_module提供。
- 用plugininte***ce結構中的函式操作外掛程式。
參考:
面試常見問題回答技巧(70題)
面試過程中我們往往會遇到很多的提問,有時候容易卡殼,這裡基本涵蓋了絕大部分面試可能出現的提問,主要是講針對提問我們應該從哪些方面去回答,給新人或者初入職場的童鞋一點參考指導 1 請你自我介紹一下你自己,2 你覺得你個性上最大的優點是什麼?3 說說你最大的缺點?4 你對加班的看法?5 你對薪資的要求?...
實驗二(第1題)
標頭檔案 ifndef seqlist h define seqlist h const int maxsize 100 class seqlist seqlist int a,int n seqlist int get int i int locate int x void insert int ...
劍指Offer 第1題
問題 在乙個二維陣列中 每個一維陣列的長度相同 每一行都按照從左到右遞增的順序排序,每一列都按照從上到下遞增的順序排序。請完成乙個函式,輸入這樣的乙個二維陣列和乙個整數,判斷陣列中是否含有該整數。暴力法 分析 直接遍歷一遍陣列,即可判斷目標target是否存在。複雜度分析 時間複雜度 o n 2 因...