Я пытаюсь перенести мое старое расширение PHP, работающее для PHP 5.4, на PHP 7.3 (точнее, 7.3.0 RC3).
Я строю расширение с помощью Visual Studio 2017 для Windows 10Pro x64, сборка как для архитектуры x64, так и для архитектуры x86.
Расширение предоставляет простую функцию (среди прочих), которая принимает массив в качестве аргумента, возвращает логическое значение и выдвигает несколько строк в массив.Массив ввода обычно пуст.
Вот код c, на котором я сосредоточился, который нацелен на PHP 5.x и PHP 7.x:
ZEND_FUNCTION(TestUpdateArray)
{
zval *zArr;
zend_bool retVal = FALSE;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &zArr) != FAILURE)
{
if (Z_TYPE_P(zArr) == IS_ARRAY)
{
char str[256];
for (int i = 1; i < 11; i++)
{
sprintf_s(str, "This is a test %d", i);
#if PHP_VERSION_ID > 70000
add_next_index_string(zArr, str);
#else
add_next_index_string(zArr, str, true);
#endif
}
retVal = TRUE;
}
}
RETURN_BOOL(retVal);
}
И это простоPHP-скрипт, который я использую, чтобы попробовать его:
<code><?php
$arr = [];
$retVal = TestUpdateArray($arr);
echo "<pre>";
var_export($retVal);
echo "\n";
var_export($arr);
echo "
";
Вывод:
true
array (
0 => 'This is a test 1',
1 => 'This is a test 2',
2 => 'This is a test 3',
3 => 'This is a test 4',
4 => 'This is a test 5',
5 => 'This is a test 6',
6 => 'This is a test 7',
7 => 'This is a test 8',
8 => 'This is a test 9',
9 => 'This is a test 10',
)
Хотя функции отлично работают в PHP 5.4, когда
$arr = [];
, httpd / php выдает исключение, а затем просто падает на PHP 7.3 с объявленным $ arr, как указано выше:
Что такоеменя интересует то, что я получаю совершенно другое поведение на 7.3, если $ arr объявлен так:
$arr = ['test'];
В этом случае как на 5.4, так и на 7.3 функция корректно добавляет 10 'Это тест x'строк массива, конечный результат:
true
array (
0 => 'test',
1 => 'This is a test 1',
2 => 'This is a test 2',
3 => 'This is a test 3',
4 => 'This is a test 4',
5 => 'This is a test 5',
6 => 'This is a test 6',
7 => 'This is a test 7',
8 => 'This is a test 8',
9 => 'This is a test 9',
10 => 'This is a test 10',
)
В свете того, что я видел, я предполагаю, что, учитывая различия и оптимизацию, представленные в PHP 7, виртуальная машина PHP делаетфактически не выделяет место для элементов массива (когда он объявлен пустым), но затем add_next_index_string function ожидает, что это так (пожалуйста, не стесняйтесь меня поправлять).
Итак, я спрашиваю, как правильно проверить и (в конечном итоге) инициализировать пустой массив, переданный вZEND_FUNCTION для внесения изменений (в массив) в вызывающий скрипт?
Я также пытался использовать функцию init_array на zArr zval, но в этом случае вызывающий скрипт не получает добавленные строки (я думаю, что ссылка на $ arr теряется при вызове init_array).
РЕДАКТИРОВАТЬ после комментария NikiC:
, когда я добавил вопрос, это было объявление функции:
ZEND_FE(TestUpdateArray, NULL)
после комментария NikiC я добавил следующий аргумент:
ZEND_BEGIN_ARG_INFO_EX(arginfo_test_update_array, 0, 0, 1)
ZEND_ARG_ARRAY_INFO(1, update_array, 0)
ZEND_END_ARG_INFO()
и обновил код функции:
ZEND_FUNCTION(TestUpdateArray)
{
zval *zArr;
zend_bool retVal = FALSE;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &zArr) != FAILURE)
{
if (Z_ISREF_P(zArr))
{
ZVAL_DEREF(zArr);
SEPARATE_ARRAY(zArr);
}
if (Z_TYPE_P(zArr) == IS_ARRAY)
{
char str[256];
for (int i = 1; i < 11; i++)
{
sprintf_s(str, "This is a test %d", i);
#if PHP_VERSION_ID > 70000
add_next_index_string(zArr, str);
#else
add_next_index_string(&myArr, str, true);
#endif
}
retVal = TRUE;
}
}
RETURN_BOOL(retVal);
}