php擴充中使用者自訂的方法有兩大類:一類是函數(獨立存在),一類是方法(依附於類和對象)。本文先說明下函數。
構造一個新的函數的原理如下:聲明並實現,實現完成後在某些特定的地方寫代碼告訴Zend引擎(註冊)。完成這兩步後就可以了。
假如需要實現一個foo()的方法,可以直接在php指令碼中調用: php -r "foo();"
第一步:聲明和實現
聲明和實現使用PHP_FUNCTION(foo){...}或者ZEND_FUNTION(foo){...},這兩個宏的作用完全相同,區別在於較老版本的php擴充都是使用PHP_FUNCTION,新的擴充使用ZEND_FUNTION,換了個馬甲。
在宏的{...},可以完成具體的商務邏輯,比如最簡單的輸入一個字串什麼的。
ZEND_FUNTION(foo){php_printf("hello foo/n");}
這樣即完成了函數的聲明和實現。
第二步:向Zend引擎註冊該函數
在所產生的擴充原始碼中有如下類似的結構:
- function_entry foo_functions[] = {
- { NULL, NULL, NULL }
- };
這個結構裡面即是用來給延伸註冊自訂函數的地方,我們先寫上註冊的代碼
- function_entry foo_functions[] = {
- PHP_FALIAS(foo, foo, NULL)
- { NULL, NULL, NULL }
- };
可以看到增加了一行語句,PHP_FALIAS也是Zend提供的一個宏,PHP_FALIAS的意思是向Zend註冊進去一個函數,同時聲明了在php指令碼中這個函數的名稱。第一個參數是在普通php指令碼中調用的名稱,第二個參數是向Zend註冊的在第一步中聲明的函數名稱,第三個為NULL和函數的參數傳遞有管,暫時不管它,置為NULL就可以了。
和上面相同,PHP_FALIAS也可以使用ZEND_FALIAS代替,換個馬甲而已。
編譯完成後,就可以這樣調用了:
- <?PHP
- foo();
- ?>
如果我們把PHP_FALIAS(foo,foo,NULL)修改為 PHP_FALIAS(foo1,foo,NULL), 則可以這樣調用:
- 1. <?PHP
- 2. foo1();
- 3. ?>
宏的含義:
PHP_FUNCTION(foo)宏展開後,得到的C代碼如下:
- zif_foo_echo (ht=0, return_value=0x86c3620, return_value_ptr=0x0, this_ptr=0x0, return_value_used=0)
可以發現該方法被加了首碼zif_,而且多了5個參數。這些參數都是自動添加進去的,具體含義現在不用管它,我們只關注函數名的改變。
其實,所有類似foo的擴充中自訂的方法最終編譯完成後都會帶上zif_的首碼, 我們通過nm檢查產生的so檔案也能夠看出來。
而PHP_FALIAS(foo,foo,NULL)這個宏呢,會首先把第二個參數添加上zif_的首碼,然後再註冊到Zend的引擎中。通過這個宏完成php指令碼中的方法名和Zend引擎中真實的方法名的映射。
zif_的意義:
可以防止擴充中定義的方法和Zend本身具有的方法重名,起到了命名空間的作用。