PHP

PHP7源码系列-写一个php拓展

2019年4月11日

ext_skel生成骨架

./ext_skel --extname=array_median

修改config.m4

解开注释

dnl PHP_ARG_WITH(array_median, for array_median support,
dnl Make sure that the comment is aligned:
dnl [  --with-array_median             Include array_median support])

添加函数显示

const zend_function_entry array_median_functions[] = {
    PHP_FE(confirm_array_median_compiled,   NULL)       /* For testing, remove later. */
    PHP_FE(array_median,    NULL)
    PHP_FE_END  /* Must be the last line in array_median_functions[] */
};

编写函数

示例

实现一个函数,获取一个数组的中位数
float array_median(array $arr)

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "php.h"
#include "php_ini.h"
#include "ext/standard/info.h"
#include "php_array_median.h"
#include "zend_hash.h"
#include "ext/standard/php_array.h"
#include "zend_types.h"
#include "Zend/zend_operators.h"


static int php_array_data_compare_numeric(const void *a, const void *b) /* {{{ */
{
    Bucket *f;
    Bucket *s;
    zval *first;
    zval *second;

    f = (Bucket *) a;
    s = (Bucket *) b;

    first = &f->val;
    second = &s->val;

    if (UNEXPECTED(Z_TYPE_P(first) == IS_INDIRECT)) {
        first = Z_INDIRECT_P(first);
    }
    if (UNEXPECTED(Z_TYPE_P(second) == IS_INDIRECT)) {
        second = Z_INDIRECT_P(second);
    }

    return numeric_compare_function(first, second);
}

PHP_FUNCTION(array_median)
{
    zval *array;
    zval *ret;
    zval *ret2;
    double median;

    if (zend_parse_parameters(ZEND_NUM_ARGS(), "a", &array) == FAILURE) {
        return;
    }

    // 排序
    if (zend_hash_sort(Z_ARRVAL_P(array), php_array_data_compare_numeric, 1) == FAILURE) {
        RETURN_FALSE;
    }
    // 数组大小
    int length = zend_hash_num_elements(Z_ARRVAL_P(array));

    if(length % 2 == 0) {
            ret = zend_hash_index_find(Z_ARRVAL_P(array), (length /2));
            ret2 = zend_hash_index_find(Z_ARRVAL_P(array), (length / 2) - 1);
            median = (double)(zval_get_long(ret) + zval_get_long(ret2)) / 2;        
    } else {
            ret = zend_hash_index_find(Z_ARRVAL_P(array), (length / 2));
            median = (double)zval_get_long(ret);
    }   

    ZVAL_DOUBLE(return_value, median);

}

const zend_function_entry array_median_functions[] = {
    PHP_FE(confirm_array_median_compiled,   NULL)       /* For testing, remove later. */
    PHP_FE(array_median,    NULL)
    PHP_FE_END  /* Must be the last line in array_median_functions[] */
};
var_dump(array_median([1, 5, 5, 2]));
// float(3.5)
var_dump(array_median([1, 5, 5]));
// float(5)

编写php拓展的其他方法

zephir

https://docs.zephir-lang.com/0.11/en/tutorial

发表评论

电子邮件地址不会被公开。 必填项已用*标注