PHP擴展詳解(一)

PHP詳解php

一個php實例,當被調用的時候,都會一次通過Module init,Request init,Request shutdown,Module shutdown四個過程.執行次數由SAPI(server abstraction API,服務器抽象化程序接口)來決定。數組

1)Call each extension's MINIT這個過程在載入的時候被調用安全

PHP_MINIT_FUNCTION(擴展名稱){
  /*註冊常量或者初始化操做*/
  return SUCCESS; 
}

2)Request服務器

PHP_RINT_FUNCTION(擴展名稱){
  /*處理請求*/
  return SUCCESS;
}

3)Execute函數

執行php階段,主要是把PHP文件編譯成Opcodes而後在php虛擬機下執行線程

ps:能夠安裝VLD擴展來查看php的opcode詳細內容翻譯

4)Call each extension's RESHUTDOWNcode

請求處理完進入結束狀態,通常腳本執行到結尾,或者經過調用exit()或者die()函數PHP將進入結束狀態,結束也分爲兩個環節,一個在請求後(RSHUTDOWN),一個在SAPI生命週期結束時候(MSHUTDOWN)server

PHP_RSHUTDOWN_FUNCTION{
  return SUCCESS;
}

PHP_MSHUTDOWN_FUNCTION{
  /*註銷持久化資源*/
  return SUCCESS;
}

在請求一個php頁面,php基本上按照這個流程來執行的。接口

ZEND引擎

Zend引擎是腳本語言引擎,主要工做是解析,翻譯和執行php腳本,主要執行兩個功能

  • 編譯php腳本,輸出Opcodes
  • 解析執行Opcodes,輸出結果

當咱們執行./ext_skel --extname=擴展名稱的時候活建立你的擴展名稱.c文件

結構以下所示

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
/** 包含頭文件引入所需的配置文件API等**/
#include "php.h"
/*在php擴展中,必須包含php.h頭文件,它位於main目錄下,這個文件包含構建擴展時必須的各類宏和API定義*/
#include "php_ini.h"
#include "ext/standard/info.h"
#include "php_php_list.h"
/* True global resources - no need for thread safety here */
static int le_php_list;
/*聲明ZEND函數塊*/
/*ZEND 引擎經過zend_function_entry 結構數組把聲明的導出函數引入內部*/
const zend_function_entry php_list_functions[] = {
	PHP_FE(confirm_php_list_compiled,	NULL)		
	PHP_FE_END 
 /*必須以PHP_FE_END結尾*/
 /*早期的php是以{NULL,NULL,NULL}結尾,如今ZEND把這個和宏綁定在一塊兒了*/
  /*
  #define PHP_FE_END      ZEND_FE_END
  #define ZEND_FE_END            { NULL, NULL, NULL, 0, 0 }
  */
};
/*聲明ZEND模塊*/
zend_module_entry php_list_module_entry = {
#if ZEND_MODULE_API_NO >= 20010901
	STANDARD_MODULE_HEADER,
#endif
	"php_list",
	php_list_functions,
	PHP_MINIT(php_list),
	PHP_MSHUTDOWN(php_list),
	PHP_RINIT(php_list),		
	PHP_RSHUTDOWN(php_list),	
	PHP_MINFO(php_list),
#if ZEND_MODULE_API_NO >= 20010901
	PHP_PHP_LIST_VERSION,
#endif
	STANDARD_MODULE_PROPERTIES
};
/*實現get_moudle()函數*/
#ifdef COMPILE_DL_PHP_LIST
ZEND_GET_MODULE(php_list)
#endif

/*php的生命週期*/

PHP_MINIT_FUNCTION(php_list)
{
	return SUCCESS;
}
PHP_MSHUTDOWN_FUNCTION(php_list)
{
	return SUCCESS;
}
PHP_RINIT_FUNCTION(php_list)
{
	return SUCCESS;
}
PHP_RSHUTDOWN_FUNCTION(php_list)
{
	return SUCCESS;
}
/*此處配置的是顯示在phpinfo()擴展名下的內容*/
PHP_MINFO_FUNCTION(php_list)
{
	php_info_print_table_start();
	php_info_print_table_header(2,"first","second");
	php_info_print_table_row(2,"mother","fucker");
	php_info_print_table_row(2,"fill","fucker");
	php_info_print_table_end();
}
/*實現導出函數*/
PHP_FUNCTION(confirm_php_list_compiled)
{
	char *str = NULL;
	//獲取輸入的個數
	int argc = ZEND_NUM_ARGS();
	int str_len; /* 字符串 長度*/
	long n;
	char *result;
	char *ptr;
	int result_length;
	if(zend_parse_parameters(argc 		TSRMLS_CC,"sl",&str,&str_len,&n)==FAILURE)
		return ;
	//獲取字符的總長度(字符串長度 * 重複次數)
	result_length = (str_len)*n;
	//分配空間
	result = (char *) emalloc(result_length+1);
	ptr = result;
	while(n--){
		memcpy(ptr,str,str_len);
		ptr+=str_len;
	}
	*ptr ='\0';
	RETURN_STRINGL(result,result_length,0);

}

取得用戶傳遞的參數

php支持可變參數,能夠使用ZEND_NUM_ARGS(傳入參數的數量)宏實現,其實這個宏等於參數ht。

取得參數的實體

int zend_parse_parameters(int nums 	TSRMLS_CC,"char * type",....)
  /*
  第一個參數 nums:表名要接受參數的個數
  第二個參數	TSRMLS_CC:是否啓用線程安全
  第三個參數:指定傳來參數的類型(字符串)
  剩下的參數:根據第三個參數類型聲明不一樣的地址
  注:字符串‘s’,須要使用兩個變量來保存
  */

待續....

相關文章
相關標籤/搜索