Как использовать std :: vector в PHP с помощью SWIG - PullRequest
10 голосов
/ 07 декабря 2011

Я работаю над переносом C ++ API в PHP с использованием SWIG.Я в основном там, но у меня проблемы с функцией, которая возвращает вектор.Заголовок выглядит примерно так:

#include <vector>

namespace STF
{
class MyClass
{
    public:
        const std::vector<MyOtherClass> &getList();
};
}

Файл интерфейса выглядит следующим образом:

%include <std_vector.i>
%import "STF_MyOtherClass.i"

%{
    #include "STF_MyOtherClass.h"
    #include "STF_MyClass.h"
%}

%include "STF_MyClass.h"

Кажется, я могу нормально вызывать функцию, но вместо этого она возвращает ресурс PHPобъекта.В частности, это ресурс типа: "_p_std__vectorT_STF__MyClass_t".

Как я могу получить это, чтобы вернуть объект, который я могу перебрать (желательно с циклом foreach) или как я могу перебрать этот ресурс?

Обновление:

Я работал над решением, основанным на том, что я прочитал здесь: http://permalink.gmane.org/gmane.comp.programming.swig/16817

В основном я пытаюсь преобразоватьvector в массив python:

%typemap(out) std::vector<STF::MyOtherClass>
{
    array_init( return_value );

    std::vector<STF::MyOtherClass>::iterator itr;

    itr = $1.begin();

    for( itr; itr != $1.end(); itr++ )
    {
        zval* tmp;

        MAKE_STD_ZVAL( tmp );
        SWIG_SetPointerZval( tmp, &*itr, $descriptor(STF::MyOtherClass*), 2 );

        add_next_index_zval( return_value, tmp );
    }
}

Это очень близко к работе.Я установил точку останова внутри кода оболочки в SWIG_ZTS_SetPointerZval.Когда он идет на инициализацию объекта, он делает zend_lookup_class для «stf__myotherclass», который завершается ошибкой (он не находит clasS).Я не уверен, почему он не может найти класс.

Ответы [ 2 ]

7 голосов
/ 07 декабря 2011

Вы почти у цели, но кроме %include <std_vector.i> вам также понадобится что-то вроде:

%template (MyVector) std::vector<MyOtherClass>;

Это указывает SWIG выставлять векторы MyOtherClass на целевой язык как типназывается MyVector.Без этого SWIG не знает, для каких типов вы хотите создать экземпляр std::vector, поэтому он сводится к переносу по умолчанию.

Примечание:

Есть ли причина, по которой вы получилиconst в const std::vector<MyOtherClass> getList(); когда это не ссылка?Я бы либо сделал его ссылкой и также сделал бы метод const (const std::vector<MyOtherClass>& getList() const;), либо полностью отбросил бы const, поскольку он там ничего не делает.

1 голос
/ 15 декабря 2011

В конце концов это то, что я сделал, чтобы преобразовать вектор в массив PHP (поместите это в файл интерфейса для MyOtherClass):

%typemap(out) const std::vector<STF::MyOtherClass>&
{
    array_init( return_value );

    std::vector<STF::MyOtherClass>::const_iterator itr;

    itr = $1->begin();

    for( itr; itr != $1->end(); itr++ )
    {
        zval* tmp;

        STF::MyOtherClass * res = new STF::MyOtherClass( *itr );

        MAKE_STD_ZVAL( tmp );

        swig_type_info type = *$descriptor(STF::MyOtherClass*);
        type.name = (char*)"_p_CustomNamespace\\MyOtherClass";

        SWIG_SetPointerZval( tmp, res, &type, 2 );

        add_next_index_zval( return_value, tmp );
    }
}

Шаблон%, который awoodland у меня не работалЯ думаю, что это, вероятно, потому что я не поместил класс PHP в другое пользовательское пространство имен.Вместо этого я сделал это вручную и передал именно тот класс php, который хотел использовать.

...