如何返回 C++ 数组来自 PHP 扩展的对象

发布于 2024-09-02 01:12:31 字数 1248 浏览 17 评论 0原文

我需要让我的 PHP 扩展返回一个对象数组,但我似乎不知道如何做到这一点。

我有一个用 C++ 编写的 Graph 对象。 Graph.getNodes() 返回一个 std::map。这是我当前的代码:

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 failure

意味着 getNodes() 函数成功循环遍历我的 2 节点列表,返回,然后出现段错误。我做错了什么?

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

I have a Graph object written in C++. Graph.getNodes() returns a std::map<int, Node*>. Here's the code I have currently:

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

meaning the getNodes() function loops successfully through my 2-node list, returns, then segfaults. What am I doing wrong?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

还给你自由 2024-09-09 01:12:31

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

I simply needed to MAKE_STD_ZVAL(node_zval). A secondary issue with this code was that I was reusing this zval pointer, thus overwriting every previous zval and ending up with an array full of the same object. To remedy this, I initialize node_zval for each loop. Here's the final 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);
        }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文