在 Linux 有 dynamic library 這個東西,這個東西的好處就是可以把常用的功能獨立出來,可以減少 code size,那它究竟是怎麼做的呢?研究了一下 所以寫了一段 sample.
下面這一個是一個簡單的BMI (Body Mass index), 公式是體重除以身高(公尺)的平方.
// func.h
typedef void (*METHOD_DESC)();
typedef float (*BMI)(float, float);
typedef struct _BMI_ {
METHOD_DESC m_des;
BMI bmi_c;
} BMI_MAI
定義一個型別為 BMI_MAI 的 structure , 一個是描述此 function 功能, 另一個是 BMI 的本體.
//lib_bmi.c
#include "func.h"
#include <stdio.h>
void BMI_DESC() {
printf("This is BMI program\n");
}
float BMI_CALC(float w, float h) {
float result;
float tmp_h;
tmp_h = (h/100);
result += (w/(tmp_h*tmp_h));
return result;
}
BMI_MAIN _bmi_main_ = {
BMI_DESC,
BMI_CALC
};
BMI_MAIN *get_func() {
return &_bmi_main_;
}
可以透過 "gcc -shared -fPIC lib_bmi.c -o lib_bmi.so" 將此 library編譯成share library
最後就是實際呼叫這個 main function.
//main.c
#include <stdio.h>
#include <dlfcn.h>
#include "func.h"
typedef BMI_MAIN *(*get_func)();
float FIND_FUNC(char *share_lib, int w, int h) {
void *func;
BMI_MAIN *f;
float result;
func = dlopen(share_lib, RTLD_LAZY);
if (!func) {
printf("Open func error\n");
return -1;
}
get_func get_func_f;
get_func_f = (get_func)dlsym(func, "get_func");
if (!get_func_f) {
printf("dlsym error\n");
dlclose(func);
return -1;
}
f = get_func_f();
f->m_des();
result = f->bmi_c(w, h);
dlclose(func);
return result;
}
int main() {
float res;
res = FIND_FUNC("/home/chris/elf/dynamic/lib_bmi.so", 70, 170);
printf("BMI = %.2f\n", res);
}
gcc main.c -o main -ldl // 因為有使用到 dlopen 所以要引用 libdl
這樣就可以了, 不過這個例子是 hard code 的我傳入的是一個身高 170 cm, 體重為 70 的 BMI 所以還是有可以改善的空間. ^^
當然以後可能還會有別的計算公式一直更新,這時我們所開發的 main.c, 因為是使用 share library 所以我們只要更新 lib_bmi.c 這一隻就可以了而不需要重新 compiler main.c.