PHP擴展開發(二)

上文咱們學會了如何快速的進行一個PHP擴展的hello world! 下面咱們將學習如何傳遞參數php

###必要知識點函數

1.變量存儲結構(php 5.6 src/ZEND/zend.h)源碼分析

typedef union _zvalue_value {
        long lval;       // long value
        double dval;     // double value
        struct {
                char *val;
                int len;
        } str;
        HashTable *ht;    //
        zend_object_value obj;
        zend_ast *ast;
} zvalue_value;

struct _zval_struct {
        // Variable information 
        zvalue_value value;             // value 
        zend_uint refcount\__gc;
        zend_uchar type;                // active type 
        zend_uchar is_ref\__gc;
};

最終造成一個[這個就是PHP的變量] typedef struct _zval_struct zval; 其實際值存儲在 zval.value 判斷是否爲引用 is_ref__gc 判斷引用的次數 refcount gc [PHP的寫時複製特性] 判斷值的類型 type學習

###源碼分析 咱們打開zend_API.c 能夠看到不少關於變量的處理的函數。ui

好比 ZEND_API int zend_get_parameters(int ht, int param_count, ...)code

ZEND_API int _zend_get_parameters_array(int ht, int param_count, zval **argument_array TSRMLS_DC)orm

ZEND_API int zend_get_parameters_ex(int param_count, ...)element

ZEND_API int _zend_get_parameters_array_ex(int param_count, zval ***argument_array TSRMLS_DC)開發

ZEND_API int zend_parse_parameters ......get

咱們來參考一下原來的代碼。 打開文件 phpsrc/ext/standard/var.c

咱們看PHP是如何實現var_dump方法的

87 PHPAPI void php_var_dump(zval **struc, int level TSRMLS_DC) /* {{{ */
  88 {
  89     HashTable *myht;
  90     const char *class_name;
  91     zend_uint class_name_len;
  92     int (*php_element_dump_func)(zval** TSRMLS_DC, int, va_list, zend_hash_key*);
  93     int is_temp;
  94 
  95     if (level > 1) {
  96         php_printf("%*c", level - 1, ' ');
  97     }
  98 
  99     switch (Z_TYPE_PP(struc)) {
 100     case IS_BOOL:
 101         php_printf("%sbool(%s)\n", COMMON, Z_LVAL_PP(struc) ? "true" : "false");
 102         break;

           ......
    }


173 line 
PHP_FUNCTION(var_dump)
 173 {
 174     zval ***args;
 175     int argc;
 176     int i;
 177 
 178     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "+", &args, &argc) == FAILURE) {
 179         return;
 180     }
 181 
 182     for (i = 0; i < argc; i++) {
 183         php_var_dump(args[i], 1 TSRMLS_CC);
 184     }
 185     efree(args);
 186 }

能夠發現 和上節說的同樣 首先定義 PHP_FUNCTION(函數名){實現} 那咱們發現沒有參數怎麼辦?

這裏就要用到咱們開始說的方法了 178行 zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "+", &args, &argc)

明顯由其得到了 參數 和 參數的個數

而後調用了函數的實現體

到此,PHP擴展開發怎麼調用函數,思路就已經很明確了。

###實踐 咱們仍是依照昨天的example,今天咱們寫一個A+B的方法

首先,咱們定義一個方法

PHP_FUNCTION(example_add){
        long a,b;
        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ll", &a, &b) == FAILURE) {
              return;
        }
        
        //添加要作的操做
       
    }

咱們加入咱們要實現的A+B功能

printf("%d\n",a+b);

一樣,咱們添加到functions

static const zend_function_entry t2_functions[] = {
    //在這加入方法的定義
    PHP_FE(example_add,NULL)
     {NULL, NULL, NULL}
}

從新編譯安裝,咱們就能夠運行

<?php example_add(3,5); ?>

輸出8

相關文章
相關標籤/搜索