template type as struct data member in SWIG
Asked Answered
A

1

6

I am writing a PHP wrapper for a C++ library using SWIG, but I am having trouble using a structure with an instance of a template type as a data member.

Suppose I have the following header file:

template <typename>
struct myvector
{
};

struct S
{
    myvector<int> v;
};

myvector<int> foo();
S bar();

and interface file:

%module test
%{
#include "test.hpp"
%}

%include "test.hpp"
%template(IntVec) myvector<int>;

When I try to use a function that directly returns an myvector, it works fine:

$v1 = test::foo();

However, when I try to use a function that returns an S object, and try to access its data member which is of type myvector:

$s = test::bar();
$v2 = $s->v;

I get the following error at runtime:

PHP Fatal error:  Class 'myvectorT_int_t' not found in test.php on line 145

I am probably missing something from my interface file, but I don't know what. Can anyone help?

Anguilla answered 4/5, 2012 at 21:57 Comment(1)
Is myvector belong to some namespace?Imine
F
3

As far as I can make out this is a SWIG bug. Someone else has already reported it in fact. Fortunately there's a simple, reliable workaround via PHP's class_alias:

%module test
%{
#include "test.h"
%}

%pragma(php) code="
# This code is inserted as a workaround for template bugs with SWIG
class_alias('IntVec', 'myvectorT_int_t');
"

%include "test.h"
%template(IntVec) myvector<int>;

The pragma here inserts the code to setup the alias at the start of the generated PHP file.

(There's another possible work around too - rather than using public member variables access via getter/setter functions works as expected)

The bug report also mentions another possible workaround although I'm not keen on that since it requires using a rather ugly name for the template type.


Justification for bug assumption

The code for __get includes:

$c=substr(get_resource_type($r), (strpos(get_resource_type($r), '__') ? strpos(get_resource_type($r), '__') + 2 : 3));
                        return new $c($r);

When you get here $c is set to myvectorT_int_t which would be correct except for the %template directive.

When we add a myvector<int> get() function to S the generated code results in:

 $c=substr(get_resource_type($r), (strpos(get_resource_type($r), '__') ? strpos(get_resource_type($r), '__') + 2 : 3));
 if (!class_exists($c)) {
     return new IntVec($r);
 }
 return new $c($r);

which crucially includes the generic code that would be correct without the %template and as special check to see if it's actually an IntVec.

There's also a comment in the Source/Modules/php.cxx:

// FIXME: Currently we always use call_user_func for __get, so we can
// check and wrap the result.  This is needless if all the properties
// are primitive types.  Also this doesn't handle all the cases which
// a method returning an object does.

Finally the code generated by the same interface file for Java is correct.

Flemming answered 10/5, 2012 at 20:54 Comment(6)
Your workaround works - thanks! Are you a SWIG developer by any chance? ;)Anguilla
@Anguilla - no connection to SWIG other than I use it a lot and I like the hard questions that nobody else seems to answer on SO. I'm not familiar enough with the internals to patch the problem properly.Flemming
I see. The reason I asked is that I'm a bit disappointed with SWIG's apparent level of maintenance and support, compared to other open-source projects - bugs in basic features like this being open for months, questions on the swig-user mailing list going unanswered, and so on. It makes me wonder whether SWIG is suitable for use in a production environment. What do you think, as someone who uses SWIG a lot? Perhaps it's just the PHP module that's being neglected?Anguilla
@high my perception is that swig is well maintained and cared for generally but that the PHP backend is much less polished than the Python or Java ones I normally use.Flemming
I've been using your suggested workaround and it seems to be pretty reliable. Bounty awarded, and thanks again! By the way, if you enjoy tackling SWIG-related questions, here's another one: #10577575Anguilla
I take back what I said about PHP being less cared for - it's been fixed with what looks like a pretty comprehensive overhaul quite quickly.Flemming

© 2022 - 2024 — McMap. All rights reserved.