Как вернуть массив объектов C ++ из расширения PHP - PullRequest
2 голосов
/ 19 мая 2010

Мне нужно, чтобы мое расширение PHP возвращало массив объектов, но я не могу понять, как это сделать.

У меня есть Graph объект, написанный на C ++. Graph.getNodes() возвращает std::map<int, Node*>. Вот код, который у меня есть на данный момент:

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

zend_class_entry *node_ce;

тогда

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("]");
}

Когда я запускаю php -r '$g = new Graph(); $g->getNodes();', я получаю вывод

XX]Segmentation fault

означает, что функция getNodes () успешно проходит по моему списку из 2 узлов, возвращает, затем segfaults. Что я делаю не так?

1 Ответ

5 голосов
/ 20 мая 2010

Мне просто нужно было MAKE_STD_ZVAL (node_zval). Вторая проблема с этим кодом заключалась в том, что я использовал этот указатель zval, перезаписывая каждый предыдущий zval и получая массив, полный того же объекта. Чтобы исправить это, я инициализирую node_zval для каждого цикла. Вот окончательный код:

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);
        }
}
...