AterCattus
AterCattus

Reputation: 41

Can I pass the string in PHP extension by reference with separating from other variables?

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

Answers (1)

hek2mgl
hek2mgl

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

Related Questions