如何从PHP扩展返回C ++对象数组

时间:2010-05-19 18:56:00

标签: php c++ arrays object php-extension

我需要让我的PHP扩展返回一个对象数组,但我似乎无法弄清楚如何做到这一点。

我有一个用C ++编写的Graph对象。 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节点列表成功循环,返回,然后是段错误。我做错了什么?

1 个答案:

答案 0 :(得分:5)

我只需要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);
        }
}