Solved thread

This post is marked as solved. If you think the information contained on this thread must be part of the official documentation, please contribute submitting a pull request to its repository.

how can I use a reference parameter?

how can I use a reference parameter?

for example :

       public function test (int &mytest) ->void
       {
                if empty mytest
                {
                        let mytest=0;
                }
                else
                {
                        let mytest++;
                }
       }


960
Accepted
answer

It is not possible for now



136
edited Jun '16

you can write something like this:

class TestClass
{
    // But be careful with static typed parameters
    public static function inc(int pass_by_ref, int step)
    {
        int i;

        let i = step + pass_by_ref;

        echo "passed value: ", pass_by_ref, "\n";
        echo "incremented value: ", i, "\n";
        %{
            // But be careful with static typed parameters, his names with _param postfix
            int refcount__gc = pass_by_ref_param->refcount__gc;

            pass_by_ref_param->refcount__gc = 1;
            zval_ptr_dtor(&pass_by_ref_param);

            MAKE_STD_ZVAL(pass_by_ref_param);
            ZVAL_LONG(pass_by_ref_param, i);
            pass_by_ref_param->refcount__gc = refcount__gc;

        }%
    }


    public static function inc2(pass_by_ref, int step)
    {
        int i;

        let i = step + pass_by_ref;

        echo "passed value: ", pass_by_ref, "\n";
        echo "incremented value: ", i, "\n";
        %{
            int refcount__gc = pass_by_ref->refcount__gc;

            pass_by_ref->refcount__gc = 1;
            zval_ptr_dtor(&pass_by_ref);

            MAKE_STD_ZVAL(pass_by_ref);
            ZVAL_LONG(pass_by_ref, i);
            pass_by_ref->refcount__gc = refcount__gc;
        }%
    }
}

in php code:

<?php
use App\TestClass;

$var_by_ref = 5;
echo 'var_by_ref value: ', $var_by_ref, "\ncall inc method\n";
TestClass::inc($var_by_ref, 10);
echo 'now var_by_ref value: ', $var_by_ref, "\ncall inc2 method\n";
TestClass::inc2($var_by_ref, 10);
echo 'now var_by_ref value: ', $var_by_ref, "\n";

result will be:

var_by_ref value: 5
call inc method
passed value: 5
incremented value: 15
now var_by_ref value: 15
call inc2 method
passed value: 15
incremented value: 25
now var_by_ref value: 25


960

Can you explain little more what is going on i the C code? What process? How to apply to the other usages of passing by ref?



136

Sorry, i bad speak english, but i try to explain.

First, you must understand, this algoritm not something as php. When you write in php $a = &$b; Php create another zval which point to original zval. This method pass variable itself.

Second, this code valid only for php 5.x.x, NOT for php 7.x.x

    // zephir fetch pointers (pzval) as pass_by_ref and step_param (you can see it in ext/app/testclass.zep.c  after code generating)
    public static function inc2(pass_by_ref, int step) 
    {
        int i; // C type long i

        let i = step + pass_by_ref;

        echo "passed value: ", pass_by_ref, "\n";
        echo "incremented value: ", i, "\n";
        %{
            // save reference counter of original variable passed to method
            int refcount__gc = pass_by_ref->refcount__gc;

            // set reference counter of original variable to 1 (no other references)
            pass_by_ref->refcount__gc = 1;
            // destroying the structure (zval) pointed to the pointer (pzval)
            zval_ptr_dtor(&pass_by_ref);

            // create new structure (zval) for this pointer (pzval)
            MAKE_STD_ZVAL(pass_by_ref);
            // make php integer structure with value C long i defined by zephir
            ZVAL_LONG(pass_by_ref, i);
            // restore original variable reference counter
            pass_by_ref->refcount__gc = refcount__gc;
        }%
    }


136
edited Jun '16

With this algoritm you can do some magic things like this:

namespace App;

class TestClass
{
    public function free()
    {
        %{
            int refcount__gc = this_ptr->refcount__gc;

            this_ptr->refcount__gc = 1;
            zval_ptr_dtor(&this_ptr);

            MAKE_STD_ZVAL(this_ptr);
            ZVAL_NULL(this_ptr);
            this_ptr->refcount__gc = refcount__gc;
        }%
    }
}

in php:

use App\TestClass;

$test_class = new TestClass;
$obj = new StdClass;
$obj->cc = $test_class;
$ar = [$test_class, $obj];

print_r($ar);

$test_class->free(); // if __destruct defined his also has been called

echo "\n\n---- var_dump(\$test_class);\n";
var_dump($test_class);
echo "\n\n---- var_dump(\$ar);\n";
var_dump($ar);

result will be:

Array
(
    [0] => App\TestClass Object
        (
        )

    [1] => stdClass Object
        (
            [cc] => App\TestClass Object
                (
                )

        )

)


---- var_dump($test_class);
NULL


---- var_dump($ar);
array(2) {
  [0]=>
  NULL
  [1]=>
  object(stdClass)#15 (1) {
    ["cc"]=>
    NULL
  }
}


960

Great info. Thanks



960

Vitaliy how can I contact you? I want something to ask you



136

This forum, or vGhost2000 {at} gmail {dot} com



3.3k

Can you provide an example of an array reference?

Sorry, i bad speak english, but i try to explain.

First, you must understand, this algoritm not something as php. When you write in php $a = &$b; Php create another zval which point to original zval. This method pass variable itself.

Second, this code valid only for php 5.x.x, NOT for php 7.x.x

```php // zephir fetch pointers (pzval) as passbyref and stepparam (you can see it in ext/app/testclass.zep.c after code generating) public static function inc2(passby_ref, int step) { int i; // C type long i

   let i = step + pass_by_ref;

 echo "passed value: ", pass_by_ref, "\n";
 echo "incremented value: ", i, "\n";
 %{
     // save reference counter of original variable passed to method
     int refcount__gc = pass_by_ref->refcount__gc;

     // set reference counter of original variable to 1 (no other references)
     pass_by_ref->refcount__gc = 1;
     // destroying the structure (zval) pointed to the pointer (pzval)
     zval_ptr_dtor(&pass_by_ref);

     // create new structure (zval) for this pointer (pzval)
     MAKE_STD_ZVAL(pass_by_ref);
     // make php integer structure with value C long i defined by zephir
     ZVAL_LONG(pass_by_ref, i);
     // restore original variable reference counter
     pass_by_ref->refcount__gc = refcount__gc;
 }%

}

```



3.3k

Can you provide an example that directly returns an array of references?

edited Jul '16

Hi everyone, I have a simple solution for this problem: use a PHP function for the task of returning a reference. I have been searching for a solution to this problem for the past couple of days, and managed to get the function that requires references to work by doing the following;

<php

// In your PHP

function refValue( $val )
{
    $ref = &$val;
    return $ref;
}

?>

After you have created the refValue function in your PHP file, you can then use it in Zephir as follows;

// In your Zephir source code
var avar = "passed by value";
var bvar = "passed by reference";

some_function( avar, refValue( bvar ) );

I have successfully used this method to get a function that requires references ($mysqli->bind_param()) to work in Zephir.

Goodluck people! HTH



960

And you include this PHP file with require() in zephir?

edited Jul '16

No, the PHP file is where I use the some_function() function from Zephir, e.g.

If I am making a a Zephir class called Zef, and I am going to use this class in test.php, I will do it as follows;

<?php

// In your PHP (test.php)

function refValue( $val )
{
    $ref = &$val;
    return $ref;
}

$zef_obj = new MyNamespace\Zef();
$zef_obj->funky();

?>

Now I'll try to make an example Zephir class, plz excuse mistakes if any.

namespace MyNamespace;

Class Zef
{
    public function funky()
    {
        var avar = "passed by value";
        var bvar = "passed by reference";
        some_function( avar, refValue( bvar ) );
    }
}

The Zef class' funky() function will use the PHP refValue() function to get the reference of bvar and pass that reference to some_function().

Sorry, I cannot seem to get the code formatting as above (with the dark background)...