我正在使用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
我可能错过了我的界面文件,但我不知道是什么。有人可以帮忙吗?
答案 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相同的接口文件生成的代码是正确的。