How to return array of C ++ objects from PHP extension

I need my PHP extension to return an array of objects, but I can't figure out how.

I have an object Graph

written in C ++. Graph.getNodes()

returns a std::map<int, Node*>

. Here's the code I have:

struct node_object {
        zend_object std;
        Node * node;
};

zend_class_entry * node_ce;

then

PHP_METHOD (Graph, getNodes)
{
        Graph * graph;
        GET_GRAPH (graph, obj) // a macro I wrote to populate graph

        node_object * n;
        zval * node_zval;

        if (obj == NULL) {
                RETURN_NULL ();
        }   

        if (object_init_ex (node_zval, node_ce)! = SUCCESS) {
                RETURN_NULL ();
        }   


        std :: map nodes = graph-> getNodes ();

        array_init (return_value);

        for (std :: map :: iterator i = nodes.begin (); i! = nodes.end (); ++ i) {
                php_printf ("X");
                n = (node_object *) zend_object_store_get_object (node_zval TSRMLS_CC);
                n-> node = i-> second;
                add_index_zval (return_value, i-> first, node_zval);
        }

        php_printf ("]");
}

When I run php -r '$g = new Graph(); $g->getNodes();'

I get the output

XX]Segmentation fault

means the getNodes () function successfully completes the loop on my 2-node list, returns and then segfaults. What am I doing wrong?

+2


a source to share


1 answer


I just needed MAKE_STD_ZVAL (node_zval). The second problem with this code was that I was reusing that zval pointer, thus overwriting every previous zval and ending up with an array full of the same object. To fix this, I initialize node_zval for every loop. Here's the last code:



PHP_METHOD (Graph, getNodes)
{
        Graph * graph;
        GET_GRAPH (graph, obj) // a macro I wrote to populate graph

        node_object * n;
        zval * node_zval;

        if (obj == NULL) {
                RETURN_NULL ();
        }   

        std :: map nodes = graph-> getNodes ();

        array_init (return_value);

        for (std :: map :: iterator i = nodes.begin (); i! = nodes.end (); ++ i) {
                MAKE_STD_ZVAL (node_zval);
                if (object_init_ex (node_zval, node_ce)! = SUCCESS) {
                        RETURN_NULL ();
                }   

                n = (node_object *) zend_object_store_get_object (node_zval TSRMLS_CC);
                n-> node = i-> second;
                add_index_zval (return_value, i-> first, node_zval);
        }
}
+5


a source







All Articles