Передача значения по ссылке в модуль на с++

grom

Новичок
Разбираюсь с созданием модуля для php на с++
все вроде работает но немогу сделать передачу переменной по ссылке, чтобы она менялась внутри с++ функции

Вот код на с++
PHP:
ZEND_BEGIN_ARG_INFO_EX(arginfo_test,1,0,0)
ZEND_ARG_INFO(1,id)
ZEND_END_ARG_INFO()


PHP_FUNCTION(test);

const zend_function_entry test_functions[] = {
    PHP_FE(test, arginfo_test)
    {NULL, NULL, NULL}
};

zend_module_entry test_module_entry = {
    STANDARD_MODULE_HEADER,       // #if ZEND_MODULE_API_NO >= 20010901
    "test",                       // название модуля
    test_functions,               // указываем экспортируемые функции
    NULL,                         // PHP_MINIT(test), Module Initialization
    NULL,                         // PHP_MSHUTDOWN(test), Module Shutdown
    NULL,                         // PHP_RINIT(test), Request Initialization
    NULL,                         // PHP_RSHUTDOWN(test), Request Shutdown
    NULL,                         // PHP_MINFO(test), Module Info (для phpinfo())
    "0.1",                        // версия нашего модуля
    STANDARD_MODULE_PROPERTIES
};

ZEND_GET_MODULE(test)

PHP_FUNCTION(test)
{
    double id;
    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &id) == FAILURE) { 
         WRONG_PARAM_COUNT;
    }

id=id+1;

    RETURN_DOUBLE(id, 1); 
}
в php запускаю функцию

PHP:
$m=8;
echo test($m);
echo "m-".$m;
функция возвращает значение 9, а вот переменная $m остаеться равна 8
хотя ZEND_ARG_INFO(1,id) еденица говорит о том что переменная должна передаваться по ссылке

подскажите что не так, как передать переменную по ссылке
 

grom

Новичок
Вурдалак
Я это читал
У меня все вроде так же но не работает
где ошибка в моем коде ?
 

Вурдалак

Продвинутый новичок
По-моему, не нужно быть гением, чтобы увидеть разницу. В своём коде ты просто увеличиваешь значение локальной переменной и не сохраняешь его (RETURN_DOUBLE этого не делает и не должен). Скорее всего, тебе нужно вставить ZVAL_DOUBLE в нужное место.
 

grom

Новичок
Вурдалак
Что значит сохранить переменную ? как это сделать ?
 

tony2001

TeaM PHPClub
ext/standard/fsock.c
static void php_fsockopen_stream(INTERNAL_FUNCTION_PARAMETERS, int persistent)
zerrno и zerrstr туда передаются "по ссылке".
Т.е. это всегда должны быть "z", а не что-то другое, перед использованием их надо разрушать zval_dtor(), а потом менять их значение.
Ну и да, arginfo надо указать, чтоб Zend Engine знал про это.
 

grom

Новичок
tony2001
можно на примере что мне надо сделать, очень сложно понять то о чем вы говорите
 

tony2001

TeaM PHPClub
Я поэтому и даю на примере:
https://github.com/php/php-src/blob/master/ext/standard/fsock.c вот реальный код, который это делает.
Собственно, передача по ссылке там - это буквально несколько строк:
Код:
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &zerrno) == FAILURE) {
RETURN_FALSE;
}
...
zval_dtor(zerrno);
ZVAL_LONG(zerrno, 0);
arginfo у тебя уже есть.

По тому же принципу в исходниках смотрится любой функционал.
Просто надо вспомнить/посмотреть какая функция так делает и посмотреть её исходный код.
 

grom

Новичок
ZVAL_LONG(zerrno, 0);
в этой строке идет присвоение переменной zerrno значение 0, которое потом присвоиться пхп переменной по ссылке так ?

после этой строчки ничего не надо писать чтобы как говорил Вурдалак сохранить значение ?

Временно не могу тестить с++ модуль так как отключили свет, хочу просто понять какие строчки кода нужны и что они делают
 

tony2001

TeaM PHPClub
>ZVAL_LONG(zerrno, 0);
>в этой строке идет присвоение переменной zerrno значение 0, которое потом присвоиться пхп переменной по ссылке так ?

Это макрос, который меняет тип zval'а на LONG и присваивает ему значение 0.
zerrno - это zval, т.е. это и есть _та самая переменная_, она ничему дальше уже не присваивается.

Нет, больше ничего делать не надо. Просто принять переменную и поменять её.
Вурдалак говорит то же, что и я, но другими словами.
 

grom

Новичок
tony2001
с типом "z" получилось передать целое число по ссылке
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &zerrno) == FAILURE) {

а вот число с точкой типо duble нет
когда пишу тип ''d' то с++ модуль компилируеться нормально но потом зависает когда из пхп вызываю созданую в нем функцию

что делать с числами с плавающей запятой ? как их передавать по ссылке ?
 

Вурдалак

Продвинутый новичок
Тебе же сказали, что должно быть "z" всегда. Вместо ZVAL_LONG пиши ZVAL_DOUBLE.
 

grom

Новичок
Вурдалак
Все понял теперь работает спасибо!

А с массивом что делать как его по ссылке передать ?
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &zerrno) == FAILURE) { оставляем ?

и только в ZVAL_ как то по другому надо прописать ?
 

grom

Новичок
Вурдалак
мне сложно разобраться
вот смотрю
http://devzone.zend.com/317/extension-writing-part-ii-parameters-arrays-and-zvals/#Heading5

как раз про массивы
но вытащить готовый пример где не будет ничего лишнего сложновато, а передачи по ссылке там помоему вообще нет
в итоге надо самому придумывать, а это мягко говоря сложновато, вот я и спрашиваю здесь, там же всего пару строк, если кто знает подскажите
 

tony2001

TeaM PHPClub
>это всегда должны быть "z", а не что-то другое

вроде бы, всё однозначно, нет?
 

grom

Новичок
PHP:
    zval *arr;
    HashTable *arr_hash;
    HashPosition pointer;
    int array_count;

    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &arr) == FAILURE) {
        RETURN_NULL();
    }

    arr_hash = Z_ARRVAL_P(arr);
    array_count = zend_hash_num_elements(arr_hash);

    php_printf("The array passed contains %d elements", array_count);
сделал так получил количество элементов в массиве
а доступ как к значениям получить непонятно
наишите плз пример

или можно как то проще без hash?
 

tony2001

TeaM PHPClub
массив - это и есть хэш в PHP.
достать значения - как я и сказал, подсмотреть как это делают другие функции.
в array.c несколько десятков примеров.
 
Сверху