項目需求:
之前做項目遇到了一個需求: 需要對接c/c++封裝的so庫,需要用php調用so庫里面的方法。
需求設想:
接觸之初,腦海中腦補了下這個需求應該怎么整: 沒搞過啊,是不是把這個so庫文件當做類,然后引用這個類再執行類里的方法。(哈哈,很單純無知的想法)
拿到so庫后,查看了下,這封裝過了的,咋引用~~。 查找一番后確定了大致的實施方法: 增加php底層擴展方法,在擴展中引入庫進行編譯,編譯成功生成php的引用擴展庫,即可直接調用擴展庫方法。
實施測試階段:
因為是引用c++的擴展庫,庫里引用和opencv的一些擴展庫,里面需要很多配套的擴展,一個蘿卜一個坑,慢慢得趟出了很多坑,也獲得了很多蘿卜。
蘿卜1: 編譯中報出各種錯,不是缺少這個擴展,就是缺少那個擴展,就得針對於各種缺少的各種安裝,此過程中了解了很多擴展庫的作用。
蘿卜2: 系統性得了解了鞏固了linux的各種命令,重溫了下C語言的語法與so庫的封裝。
實施階段:
因為是需要用到php的源碼增加擴展,先現在一份和當前php環境版本一致的源碼。下載地址: http://php.net/downloads.php
將so庫的存放路徑寫入配置中保存(各個配置的環境路徑也許會有不同) 打開 cd /etc/ld.so.conf.d/ vim local.conf 將so庫存放路徑/usr/local/lib寫入保存
解壓源碼包(路徑沒要求) 打開解壓后的文件夾里的 ext文件夾,里面儲存的是php自帶的一些擴展目錄,我們所要做的就是在里面再加一個我們需要的擴展。
開始創建一個模塊test: 執行命令: sudo ./ext_skel --extname=test
執行完會生成一個test的模塊文件夾,打開test cd test
需要修改一些文件 給需要修改的文件權限 sudo chmod 777 config.m4 php_test.h test.c
1> 先修改 php_test.h 在聲明方法下 增加一個你自己定義的調取so庫的方法 如增加 test_add 方法:
PHP_FUNCTION(confirm_suone_compiled); /* For testing, remove later. */
PHP_FUNCTION(test_add); //聲明此函數 (后面test.c中將用到)
2> 修改config.m4:
PHP_ARG_WITH(test, for test support, //放開此兩行的注釋 __WITH 是引用的外部庫文件又引用了其他鏈接庫 如果是引用單一的一個so文件,即放開 __ENABLE那兩行
[ --with-test Include test support])
在底部引入擴展目錄及文件,例如需添加的so庫名稱為 gettime.so
PHP_ADD_LIBRARY_WITH_PATH(gettime,/usr/local/lib,TEST_SHARED_LIBADD)
PHP_ADD_LIBRARY_WITH_PATH(opencv_core,/usr/local/lib, TEST_SHARED_LIBADD) //引入一個opencv的鏈接庫為例 此庫都放在 /usr/local/lib 文件夾下
PHP_SUBST(TEST_SHARED_LIBADD) //加入此句表示此庫為共享庫
PHP_NEW_EXTENSION(test, test.c, $ext_shared)
3> 修改 test.c文件 (主函數文件)
const zend_function_entry test_functions[] = {
PHP_FE(confirm_test_compiled, NULL) /* For testing, remove later. */
PHP_FE(test_add,NULL) //加入此方法
{NULL,NULL,NULL}
// PHP_FE_END /* Must be the last line in suone_functions[] */
};
在文件底部,寫函數調用方法
PHP_FUNCTION(test_add){ //test_add 是上面申明的方法名
char *name=NULL; //定義類型
long len;
long uid;
If(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl", &name,&len ,&uid) == FAILURE) {
return;
}
char *data = Gettime(name,uid); //直接請求外部庫gettime.so的 Gettime函數,傳遞參數,獲取值
RETURN_STRINGL(data,strlen(data)+1,1); //返回結果值
}
每個庫的請求方法和參數結合不相同,具體根據外部庫所需要的參數為准
4> 文件修改完畢,現在執行編譯命令,生成php可直接執行的底層庫
sudo phpize
sudo ./configure --with-php-config=/usr/bin/php-config --with-test
sudo make test (先執行test 如果此步驟返回success,即可正常執行下面的安裝,如果報錯,先處理至沒錯)
sudo make install (安裝完之后會生成一個新的庫test.so 文件,將此文件復制到php的擴展庫目錄中 /usr/local/lib)
將 test.so 寫入到php.ini的配置中 Extension=test.so 如果在之前的配置中引入了整個庫文件目錄,就不需要單獨引入此文件
重啟php服務
測試結果
新建一個test.php 文件
<?php
print_r(test_add("so庫測試",1)); //test_add為擴展主方法里所寫入的方法名,即可鏈接調用gettime.so的庫文件里的方法了
?>