c ++ — вектор преобразования Swig & lt; std :: string & gt; в родной массив PHP

Я начинаю работать с swig а также phpи я хотел бы вернуть 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::vector в php массив не работает; когда я сделал свой print_r У меня есть такой результат: resource(1) of type (_p_std__vectorT_std__string_t)

1

Решение

Ваш код был довольно близок к работе, но он не был правильно применен из-за несоответствия типов. Ваша карта была написана как const std::vector<std::string> &тогда как тестовая функция, которую вы использовали, просто вернулась std::vector<std::string>не константно и не по значению, а не по ссылке.

После исправления становится очевидным, что не существует определенного типа, называемого Array в вашем коде, и это $1 на самом деле является примером std::vector<std::string>, а не указатель на. я использовал $1_ltype чтобы SWIG генерировал правильный полностью определенный тип для ввода в карту типов. Поэтому, чтобы ваш код работал, нам нужно изменить его следующим образом:

%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 является нормальным и может использоваться без дальнейшей работы.

0

Другие решения

Других решений пока нет …