I am working on wrapping a C++ API in PHP using SWIG. I am most of the way there but I am having problems with a function that returns a vector. The header looks something like this:
#include <vector>
namespace STF
{
class MyClass
{
public:
const std::vector<MyOtherClass> &getList();
};
}
The interface file looks like this:
%include <std_vector.i>
%import "STF_MyOtherClass.i"
%{
#include "STF_MyOtherClass.h"
#include "STF_MyClass.h"
%}
%include "STF_MyClass.h"
I seem to be able to call the function fine but it is returning a PHP resource instead of an object. Specifically it is a resource of type: "_p_std__vectorT_STF__MyClass_t".
How can I either get this to return an object that I can iterate through (preferably with a foreach loop) or how can I iterate through this resource?
Update:
I have been working on a solution based off of what I read here: http://permalink.gmane.org/gmane.comp.programming.swig/16817
Basically I am trying to convert the vector into a python array:
%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 );
}
}
This is very close to working. I put a breakpoint inside the wrapper code within SWIG_ZTS_SetPointerZval. When it goes to initialize the object it does a zend_lookup_class for "stf__myotherclass" which fails (it doesn't find a clasS). I am not sure why it can't find the class.
You're almost there, but as well as %include <std_vector.i>
you'll also need something like:
%template (MyVector) std::vector<MyOtherClass>;
This instructs SWIG to expose vectors of MyOtherClass
to the target language as a type called MyVector
. Without doing this SWIG doesn't know which types you want to instantiate std::vector
for, so it's reduced to the default wrapping.
Side note:
Is there a reason you've got the const
in const std::vector<MyOtherClass> getList();
when it's not a reference? I'd either make it a reference and make the method const
also (const std::vector<MyOtherClass>& getList() const;
) or drop the const
entirely since it does nothing there.
In the end this is what I did to convert the vector into a PHP array (put this in the interface file for 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 );
}
}
The %template that awoodland did not work for me. I think it is probably because I did not put the PHP class in a different custom namespace. Instead, I did this manually and passed in the exact php class I wanted it to use.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With