C PHP扩展中的类型转换问题


casting issues in C PHP extension

我正试图为指数移动平均算法构建一个PHP扩展。我是C的新手,我相信我有一些铸造问题(见下面代码中的注释行)。

预期结果:622.81176945058

实际结果:7.9131985629043E-316

代码:

double computeLastEMA(HashTable *arr_hash, double period)
{
    zval **data;
    HashPosition pointer;
    double k, n;
    int i = 0;
    k = 2.0 / ((double) period + 1.0 );
    // Compute Simple Moving Average
    for(zend_hash_internal_pointer_reset_ex(arr_hash, &pointer);
            zend_hash_get_current_data_ex(arr_hash, (void **) &data, &pointer) == SUCCESS && i < period;
            zend_hash_move_forward_ex(arr_hash, &pointer), ++i
    ) {
            n += *(double *) data;
    }
    n = n / period;
    // Compute Exponential Moving Average
    for(;
            zend_hash_get_current_data_ex(arr_hash, (void **) &data, &pointer) == SUCCESS;
            zend_hash_move_forward_ex(arr_hash, &pointer)
    ) {
            n += k * ( *(double *) data - n );
            i = *(double *) data; // !this is the casting issue!
    }
    return i;
}
PHP_FUNCTION(lastEMA)
{
    zval *values;
    HashTable *arr_hash;
    long period;
    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|l", &values, &period) == FAILURE)
    {
            RETURN_NULL();
    }
    arr_hash = Z_ARRVAL_P(values);
    RETURN_DOUBLE(computeLastEMA(arr_hash, period));
}

我做错了什么?谢谢!(事实上,我不知道"*"到底是什么意思!()

假设数组中的每个元素都是双值,则需要使用Z_DVAL_PP(data)zval **转换为double值。

for(zend_hash_internal_pointer_reset_ex(arr_hash, &pointer);
            zend_hash_get_current_data_ex(arr_hash, (void **) &data, &pointer) == SUCCESS && i < period;
            zend_hash_move_forward_ex(arr_hash, &pointer), ++i
    ) {
        double value = Z_DVAL_PP(data);
        n += value;
    }

另一个循环可以用同样的方法固定。

最后,可以在zpp中使用H类型来简化代码:

HashTable *arr_hash;
double period = 0.f;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "H|d", & arr_hash, &period) == FAILURE)
{
    RETURN_NULL();
}

我还修复了可选的period参数中潜在的类型问题。