模板类型作为SWIG中的结构数据成员

时间:2012-05-04 21:57:00

标签: php c++ templates swig language-binding

我正在使用SWIG为C ++库编写PHP包装器,但是我在使用具有模板类型实例的结构作为数据成员时遇到了问题。

假设我有以下头文件:

template <typename>
struct myvector
{
};

struct S
{
    myvector<int> v;
};

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

和界面文件:

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

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

当我尝试使用直接返回myvector的函数时,它可以正常工作:

$v1 = test::foo();

但是,当我尝试使用返回S对象的函数,并尝试访问类型为myvector的数据成员时:

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

我在运行时遇到以下错误:

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

我可能错过了我的界面文件,但我不知道是什么。有人可以帮忙吗?

1 个答案:

答案 0 :(得分:3)

据我所知,这是一个SWIG错误。其他人实际上有already reported it。幸运的是,通过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>;

此处的pragma插入代码以在生成的PHP文件的开头设置别名。

(还有另一个可能的工作 - 而不是通过getter / setter函数使用公共成员变量访问按预期工作)

bug report还提到了另一种可能的解决方法,虽然我并不热衷于此,因为它需要为模板类型使用一个相当丑陋的名称。


错误假设的理由

__get的代码包括:

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

当你到达$c时,myvectorT_int_t设置为%template,除了myvector<int> get()指令外,这是正确的。

当我们向S添加 $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); 函数时,生成的代码会生成:

%template

其中至关重要的是包含通用代码,该代码在没有IntVec 作为特殊检查的情况下是正确的,以查看它是否实际上是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. 中还有评论:

{{1}}

最后,由Java相同的接口文件生成的代码是正确的。