在 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.

arrow
arrow
    全站熱搜

    sakbk 發表在 痞客邦 留言(1) 人氣()