Swig将vector <std :: string>转换为本机PHP数组

时间:2016-11-09 08:10:53

标签: php c++ c++11 swig

我开始使用swigphp,我想将std::vector<std::string>返回到我的php代码。我试过这个(所有编译工作)

我的swig文件:

%module example
%include <std_string.i>
%include <std_vector.i>

%{
    extern std::vector<std::string> testSwig(const char *path);
%}

//try here to convert vector to native php array
%typemap(out) const std::vector<std::string> & {
    array_init($result);
    Array::const_iterator i = $1->begin();
    Array::const_iterator e = $1->end();
    for(; i != e; ++i ) {
        zval * data;
        MAKE_STD_ZVAL(data);
        ZVAL_STRINGL(data, (char*)i->c_str(), i->size(), 1);
        zend_hash_next_index_insert( HASH_OF($result), &data, sizeof(zval *), NULL );
    }
}

extern std::vector<std::string> testSwig(const char *path);

我的cpp文件:

#include <iostream>
#include <vector>

std::vector<std::string> testSwig(const char *path)
{
    std::vector<std::string> v;
    v.push_back("test 1");
    v.push_back("test 2");
    v.push_back("try vector");

    return v;
}

最后我的php文件试试这个:

<?php
    echo '<pre>';
    echo print_r(testSwig('try arg'));
    echo '</pre>';
?>

我的问题是我的转换std::vectorphp数组不起作用;当我创建print_r时,我得到了这个结果:resource(1) of type (_p_std__vectorT_std__string_t)

2 个答案:

答案 0 :(得分:1)

为Flexo提供答案。

在PHP7 zend API中,已删除MAKE_STD_ZVAL()宏(包括其他一些内容:https://wiki.php.net/phpng-upgrading

为了使此typemap与PHP7一起使用,这就是我所做的:

%typemap(out) std::vector<std::string> {
    array_init($result);
    $1_type::const_iterator i = $1.begin();
    $1_type::const_iterator e = $1.end();

    for(; i != e; ++i ) {
        add_next_index_string($result, (char*) i->c_str() );
    }
}
php中的

testSwig函数可以打印出预期的结果:

Array
(
    [0] => test 1
    [1] => test 2
    [2] => try vector
)

答案 1 :(得分:0)

您的代码非常接近工作,但由于类型不匹配而无法正确应用。您的out typemap被写为const std::vector<std::string> &,而您使用的测试函数只返回std::vector<std::string>,即不是const和按值,而不是通过引用。

通过修复它,很明显代码中没有定义名为Array的类型,$1实际上是std::vector<std::string>的实例,而不是指向on的指针。我使用$1_ltype使SWIG为typemap的输入生成正确的完全限定类型。因此,要使代码工作,我们需要对其进行修改:

%module test

%{
#include <string>
#include <vector>
%}

%typemap(out) std::vector<std::string> {
    array_init($result);
    $1_type::const_iterator i = $1.begin();
    $1_type::const_iterator e = $1.end();
    for(; i != e; ++i ) {
        zval * data;
        MAKE_STD_ZVAL(data);
        ZVAL_STRINGL(data, (char*)i->c_str(), i->size(), 1);
        zend_hash_next_index_insert( HASH_OF($result), &data, sizeof(zval *), NULL );
    }
}

%inline %{
std::vector<std::string> testSwig(const char *path)
{
    std::vector<std::string> v;
    v.push_back("test 1");
    v.push_back("test 2");
    v.push_back("try vector");

    return v;
}
%}

在Ubuntu 14.04上使用PHP 5,足以让以下测试用例按预期工作:

<?php
include('test.php');
print_r(test::testSwig('hello'));
?>

我编译并运行为:

swig -php -c++ test.i
g++ test_wrap.cpp $(php-config --includes --libs) -shared -o test.so -fPIC
php5 run.php

Array
(
    [0] => test 1
    [1] => test 2
    [2] => try vector
)

作为参考,SWIG向量和字符串类非常有用,给出:

%module test

%include <std_string.i>
%include <std_vector.i>

%template(StringVec) std::vector<std::string>;

%inline %{
std::vector<std::string> testSwig(const char *path)
{
    std::vector<std::string> v;
    v.push_back("test 1");
    v.push_back("test 2");
    v.push_back("try vector");

    return v;
}
%}

类型StringVec是理智的,可以在没有进一步工作的情况下使用。

相关问题