Swig 将向量 <std::string> 转换为原生 PHP 数组
Swig convert vector<std::string> to native PHP array
我开始使用 swig
和 php
,我想 return 一个 std::vector<std::string>
到我的 php
code.I试过这个(所有编译工作)。
我的 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 = ->begin();
Array::const_iterator e = ->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::vector
到 php
数组的转换不起作用;当我制作 print_r
时,我得到了这个结果:resource(1) of type (_p_std__vectorT_std__string_t)
您的代码几乎可以正常工作,但由于类型不匹配而未能正确应用。您的输出类型映射写为 const std::vector<std::string> &
,而您使用的测试函数只是返回 std::vector<std::string>
,即不是 const 和按值,而不是按引用。
修复后,很明显在您的代码中没有定义称为 Array
的类型,并且 </code> 实际上是 <code>std::vector<std::string>
的实例,而不是指向的指针在。我使用 _ltype
让 SWIG 为类型映射的输入生成正确的完全限定类型。因此,为了让您的代码正常工作,我们需要这样修改它:
%module test
%{
#include <string>
#include <vector>
%}
%typemap(out) std::vector<std::string> {
array_init($result);
_type::const_iterator i = .begin();
_type::const_iterator e = .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 向量和字符串 class 非常有用,给定:
%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
是正常的,无需进一步工作即可使用。
添加 Flexo 提供的答案。
在PHP7 zend API MAKE_STD_ZVAL() 宏被移除(包括一些其他的东西:https://wiki.php.net/phpng-upgrading)
为了使此类型映射与 PHP7 一起工作,我这样做了:
%typemap(out) std::vector<std::string> {
array_init($result);
_type::const_iterator i = .begin();
_type::const_iterator e = .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
)
我开始使用 swig
和 php
,我想 return 一个 std::vector<std::string>
到我的 php
code.I试过这个(所有编译工作)。
我的 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 = ->begin();
Array::const_iterator e = ->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::vector
到 php
数组的转换不起作用;当我制作 print_r
时,我得到了这个结果:resource(1) of type (_p_std__vectorT_std__string_t)
您的代码几乎可以正常工作,但由于类型不匹配而未能正确应用。您的输出类型映射写为 const std::vector<std::string> &
,而您使用的测试函数只是返回 std::vector<std::string>
,即不是 const 和按值,而不是按引用。
修复后,很明显在您的代码中没有定义称为 Array
的类型,并且 </code> 实际上是 <code>std::vector<std::string>
的实例,而不是指向的指针在。我使用 _ltype
让 SWIG 为类型映射的输入生成正确的完全限定类型。因此,为了让您的代码正常工作,我们需要这样修改它:
%module test
%{
#include <string>
#include <vector>
%}
%typemap(out) std::vector<std::string> {
array_init($result);
_type::const_iterator i = .begin();
_type::const_iterator e = .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 向量和字符串 class 非常有用,给定:
%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
是正常的,无需进一步工作即可使用。
添加 Flexo 提供的答案。
在PHP7 zend API MAKE_STD_ZVAL() 宏被移除(包括一些其他的东西:https://wiki.php.net/phpng-upgrading)
为了使此类型映射与 PHP7 一起工作,我这样做了:
%typemap(out) std::vector<std::string> {
array_init($result);
_type::const_iterator i = .begin();
_type::const_iterator e = .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
)