Reputation: 41
I have example code:
ZEND_BEGIN_ARG_INFO(arginfo_refstring, 0)
ZEND_ARG_INFO(1, s1)
ZEND_END_ARG_INFO()
const zend_function_entry refstring_functions[] = {
PHP_FE(refstring, arginfo_refstring)
PHP_FE_END
};
PHP_FUNCTION(refstring)
{
char *s1;
int s1_len;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &s1, &s1_len) == FAILURE) {
return;
}
s1[0] = 'X';
}
And php code:
$s1 = 'hello';
$s2 = $s1;
refstring($s1);
var_dump($s1, $s2);
I expect:
string(5) "Xello"
string(5) "hello"
But i got:
string(5) "Xello"
string(5) "Xello"
How can I separate
$s2
from$s1
, but keep the ability to change$s1
inside function?
I known about SEPARATE_ZVAL and co., but they did not help...
Upvotes: 2
Views: 449
Reputation: 158020
This happens because of a mechanism called copy on write.
After this lines:
$s1 = 'hello';
$s2 = $s1;
$s1
and $s2
are both independent variables (zvals), but they point to the same(!) data in memory - because both share the same value, meaning none of them has been changed so far.
If you would:
$s1 = 'foo';
... PHP would internally update the zval behind $s1
in a way that it's value points to a different portion of memory.
However, since you are modifying the value in an extension function, this function would need to take care on that itself:
PHP_FUNCTION(refstring)
{
zval *s1;
char *string;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &s1)
!= SUCCESS
) {
return;
}
// copy the value before writing to it
string = strdup(s1->value.str.val);
string[0] = 'X';
ZVAL_STRING(s1, string, 1);
}
Note that I'm using a zval *
rather than using a pure string for the input parameter.
Further note that, the above function works as expected. However, I'm not sure if there is a MACRO for that purpose which can be used more elegantly.
Upvotes: 1