C語言插件開發模式

       以前總是不明白爲什麼不同的模塊是相互獨立的編譯,相互之間不存在的調用關係, 怎麼做到在使用的時候加載不使用的時候卸載掉? 現在總算是明白了。其實就是將一個功能做成一個動態庫,在window中叫dll,在Unix/Linux中叫做so。通過配置在運行的時候,在運行的時候,通過一些特殊的函數對dll或者so進行操作。找到函數的地址,調用函數。在使用函數的時候找函數,不是使用的時候釋放就可以了。

           我也找不到合適的列子。我直接上代碼吧。通過輸入不同的so或者dll執行不同的內容。本文件以Unix/Linux中的C語言代碼爲例子。使用到的知識很簡單。就是dlopen和dlsym函數。所有的函數都在dlfcn.h頭文件中。

          

void * dlopen( const char * pathname, int mode);

pathname:so或者dll文件的路徑,在Linux中必須是以"./"或者"../"開始的相對路徑 或者 以"/"開始的絕對路徑
mode:解析so或者dll文件的方式,可以取以下值 

RTLD_LAZY:在dlopen返回前,對於動態庫中的未定義的符號不執行解析(只對函數引用有效,對於變量引用總是立即解析)。

RTLD_NOW: 需要在dlopen返回前,解析出所有未定義符號,如果解析不出來,在dlopen會返回NULL

打開錯誤返回NULL

成功,返回庫引用

.

 

 

 dlsym(void *dp, char * funtionname);
dp:已經打開的so或者dll文件句柄
functionname:要解析的文件名字

數返回值是void*,指向函數的地址

 

 

dlclose(void *dp)
關閉指定句柄的動態鏈接庫,只有當此動態鏈接庫的使用計數爲0時,纔會真正被系統卸載。

 

 

 

主函數

 

#include <stdio.h>
#include <dlfcn.h>
#include "dll.h"

int main(){
    void *dp;
    char *err;
    char fname[20];
    dll p;
    void (*init)(dll *p);
    printf("請輸入要加載模塊的名字:model1 或者model2");
    scanf("%s", fname);
    sprintf("./%s^", fname);
    dp = dlopen(fname, RTLD_LAZY);//打開動態庫。
    if( NULL == dp) {
        printf("%s\n", dlerror());
        exit(1);
    }
    init = dlsym(dp, "init");//找到init函數的地址。
    init(&p);
    printf("%s\n", p.name);

p.done();//注意這裏done雖然是so中函數。卻沒有使用使用dlsym找done函數的地址。 err = dlerror(); dlclose(dp);}model1.c

 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "dll.h"

void done(){
    printf("This is test module 1!\n");
}

void init(dll *p){
    p->name = (char *)calloc(3, sizeof(char));
    strcpy(p->name, "so1");
    p->done = done;
}

 

model1.c

 

 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "dll.h"

void done(){
    printf("This is test module 2!\n");
}

void init(dll *p){
    p->name = (char *)calloc(3, sizeof(char));
    strcpy(p->name, "so2");
    p->done = done;
}

 


dll.h 頭文件

 

typedef struct dll{
    char * name;
    void (*done)() ;
}dll;


以下爲gcc的編譯過程

 

 

 

 

gcc -rdynamic -o test  test.c dll.h -ldl  //-ldl (指定dl庫)因爲dlopen和dlsym在dl庫中
gcc -shared -o module1.so  module1.c dll.h
gcc -shared -o $module2.so module2.c dll.h


將會根據輸入的不同顯調用不同的dll中的函數。
.

 

blog: http://blog.csdn.net/rentiansheng/article/details//8606125 

 

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