我正在使用SWIG在PHP中包装C ++ API。我大部分时间都在那里,但我遇到了一个返回向量的函数的问题。标题看起来像这样:
#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
基本上我试图将矢量转换为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中的包装器代码中放置了一个断点。当它初始化对象时,它为“stf__myotherclass”执行zend_lookup_class失败(它没有找到clasS)。我不确定为什么找不到这门课。
答案 0 :(得分:7)
你几乎就在那里,但除了%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 :(得分:1)
最后,我将把矢量转换为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类。