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?

HighCommander4
  • 50,428
  • 24
  • 122
  • 194

1 Answers1

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.

Community
  • 1
  • 1
Flexo
  • 87,323
  • 22
  • 191
  • 272
  • Your workaround works - thanks! Are you a SWIG developer by any chance? ;) – HighCommander4 May 11 '12 at 01:47
  • @HighCommander4 - 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. – Flexo May 11 '12 at 08:38
  • 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? – HighCommander4 May 11 '12 at 20:25
  • @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. – Flexo May 11 '12 at 22:46
  • 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: http://stackoverflow.com/questions/10577075/iterating-over-stdmap-in-php-with-swig – HighCommander4 May 14 '12 at 03:01
  • 1
    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. – Flexo May 18 '12 at 10:55