# python import c Linux 建立動態(Shread)函式庫 應用在樹莓派 ## 1. 範例 首先要以-fPIC選項建立一object file,PIC(position-independent code),是shared library必需使用的選項,這令shared library擁有自己的動態記憶體區塊(i.e. 它使用全域記憶體偏移量表(global offset table,GOT),不受主程式的記憶體限制): ~~~ gcc -fPIC -c -Wall initapi.c gcc -fPIC -c -Wall randapi.c ~~~ 然後再將目的檔編譯成「.so」: ~~~ gcc -shared initapi.o randapi.o -o libmyrand2.so ~~~ ## 2.實例 照以上步驟編譯 樹莓派檔案有 ads8861.c current_hal.c merge_sort.c mux506.c testboard.c 另外因為有用到樹莓派週邊 需要另外下載bcm2835 library 編譯執行檔時需要 新增 -lbcm2835 例如 ~~~ gcc -o main main.c -lbcm2835 ~~~ 在製作動態節連函式庫.so時 需要先這樣編譯 ~~~ gcc -fPIC -c ads8861.c current_hal.c merge_sort.c mux506.c testboard.c ~~~ 會生成以下目的檔 ~~~ ads8861.o current_hal.o merge_sort.o mux506.o testboard.o ~~~ 再來利用目的檔生成.so檔,需要另外加入 -lbcm2835 否則樹莓派另外安裝的函式庫無法用 ~~~ gcc -shared ads8861.o current_hal.o merge_sort.o mux506.o testboard.o -o libintegrator.so -libcm2835 ~~~ 使用.so範例如下 ```c #include <stdio.h> #include <dlfcn.h> //直接使用動態連結檔so 需要 include int main(int argc, char **argv) { void *handle = dlopen("/home/pi/libintegrator.so", RTLD_LAZY); //放.so所在路徑 float (*current)(int); current = dlsym(handle, "get_avg"); //.so檔內要用的函式名稱丟進current printf("get_avg = %2.3f", (*current)(2));看印出資料有沒有成功執行 return 0; } ``` 主程式還需要編譯成執行檔,需要記得加 -ldl才能用動態連結 主程式內也要記得 include dlfcn.h 才能用動態連結 ~~~ gcc -o main main.c -ldl ~~~ 這邊用python import libintegrator.so ```python from ctypes import cdell, c_int, c_float def load_c_fun(): #load .so 放上檔案路徑 myso = cdell.LoadLibrary('./libintegrator.so') #setting input type myso.get_avg.argtypes = [c_int] #setting return type myso.get_avg.restype = c_float retrun myso if __name__ == "__main__" so = load_c_fun() for i in range(5000): j = i % 3 I = so.get_avg(j) print("I = ", I) ```