Template type as a member of structure data in SWIG

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

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 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; 

At runtime, the following error appears:

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

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

+6
source share
1 answer

As far as I can understand this, this is a SWIG error. Someone else has already reported this . Fortunately, there is a simple and reliable workaround through the PHP 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>; 

Here, the pragma inserts the code for setting the alias at the beginning of the generated PHP file.

(There's also another possible job - instead of using access to public member variables via getter / setter functions, it works as expected)

The error report also mentions another possible workaround, although I am not interested in this because it requires the use of a rather ugly name for the template type.


Justification for the mistake

The __get code 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 set to myvectorT_int_t , which will be correct, with the exception of the %template directive.

When we add the 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 generic code that would be correct without %template and as a special check to see if this is IntVec .

There is also a comment in 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.

+3
source

Source: https://habr.com/ru/post/914934/


All Articles