6

我正在使用 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

我可能从我的接口文件中遗漏了一些东西,但我不知道是什么。任何人都可以帮忙吗?

4

1 回答 1

3

据我所知,这是一个 SWIG 错误。其实已经有人举报了。幸运的是,通过 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 函数访问的公共成员变量按预期工作)

错误报告还提到了另一种可能的解决方法,尽管我并不热衷于此,因为它需要为模板类型使用一个相当难看的名称。


错误假设的理由

的代码__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.

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

于 2012-05-10T20:54:34.633 回答