swig-php 包装器使用指针,c 代码是一个数组
Posted
技术标签:
【中文标题】swig-php 包装器使用指针,c 代码是一个数组【英文标题】:swig-php wrapper uses pointer, c code is an array 【发布时间】:2010-12-21 22:55:09 【问题描述】:我正在使用 SWIG 生成一个调用“c”共享库的 php 扩展。除了以下情况外,我能够完成大多数工作......
在我的“c”代码中,我将函数声明为(请注意结构和函数名称已更改以保护无辜者):
int getAllThePortInfo(EthernetPort *ports);
在这种情况下,参数ports实际上是一个EthernetPort结构数组。在另一个“c”程序中,我可以这样称呼它......
EthernetPort ports[4];
int rval = getAllThePortInfo(ports);
<etc>
<etc>
这很好用。然后我运行 SWIG,生成我的共享库,并且所有构建都很好。我得到了可以调用的 php 代码...
$ports = new_ethernetport();
$rval = getAllThePortInfo($ports);
这会导致 PHP 抛出以下错误:php: free(): invalid pointer: 0x099cb610
所以,我尝试做类似...
$ports = array(new_ethernetport(), new_ethernetport(), new_ethernetport(), new_ethernetport());
$rval = getAllThePortInfo($ports);
但后来 PHP 抱怨... PHP 致命错误:在 getAllThePortInfo 的参数 1 中键入错误。预期 SWIGTYPE_p_EthernetPort
我认为发生的事情是 PHP(和 SWIG)不区分指针和数组,并且在包装器中,它正在考虑“指向单个结构的指针”,而实际上,它是一个结构数组.
PHP 中有什么我可以做的吗?分配一块我可以用作存储多个结构的空间的内存?
我可以通过 SWIG 做些什么来让我的包装器更好地理解我的意图吗?
我真的很感激任何建议。谢谢。
【问题讨论】:
在你的C代码中,调用者如何知道getAllThePortInfo()
需要的数组的大小?是否固定为 4?
如果您改为声明int getAllThePortInfo(EthernetPort ports[]);
会怎样?我知道 C 编译器无论如何都会将其更改为指针,但它可能会对 SWIG 产生影响?
也许您可以发布 interface.i 文件的一些相关部分。
回答您的问题... [@caf] 是的,大小是固定的。 [@netcoder] 我尝试了这种改变。它仍然是 SWIG 中的指针。在文档中,SWIG 声明它将所有数组都视为指针以方便操作。 [@mario] 我的 .i 文件没有什么特别之处。我只包含我的 .h 文件,该文件声明了函数并在其中包含一些结构和#defines。
昨晚我在阅读有关 SWIG 的 carrays.i 模块的信息。任何关于使用它来解决我的问题的cmets?我还没有让它工作,但会继续努力。
【参考方案1】:
carrays.i 确实回答了我的问题...
在 SWIG 接口文件中,我有以下几行...
%include <carrays.i>
%array_functions(EthernetPort, ethernetPortArray);
%include "my_lib.h"
"my_lib.h" 包含 EthernetPort 结构的 typedef,以及函数声明...
#define NUM_ETHERNET_PORTS 4
typedef struct
int number;
mode_t mode;
EthernetPort;
int getAllThePortInfo(EthernetPort *ports);
运行 SWIG 并构建共享库 my_lib.so 后,我可以使用以下 PHP 代码...
$ports = new_ethernetPortArray(NUM_ETHERNET_PORTS);
$rval = getAllThePortInfo($ports);
$port0 = ethernetPortArray_getitem($ports, 0);
$pnum = ethernetport_number_get($port1);
$pmode = ethernetport_mode_get($port1);
// port1 port2 port3 etc etc
delete_ethernetPortArray($ports);
php 函数 new_ethernetPortArray、ethernetPortArray_getitem、ethernetport_number_get、ethernetport_mode_get、delete_ethernetPortArray都是 SWIG 基于 .i 文件创建的。
SWIG 带来的另一个好处是在我的 php 代码中使用#define(例如 NUM_ETHERNET_PORTS),让我可以在一个地方存放一些常用数据。我喜欢。 :-)
干杯。
【讨论】:
【参考方案2】:@DoranKatt,您的解决方案也对我有用,只需稍作调整。我不得不更改 swig 文件中的顺序:
%include <carrays.i>
%include "my_lib.h"
%array_functions(EthernetPort, ethernetPortArray);
按照原始顺序,我发现它生成的代码无法编译,因为数组函数引用了稍后包含在“my_lib.h”中的类型。当然,我的代码使用了不同的名称和类型,但为了清楚起见,我保留了原始作者的姓名。
感谢您发布原始问题和答案。这把我从一个洞里挖了出来。我在 swig 文档中找不到任何关于此的内容。
【讨论】:
以上是关于swig-php 包装器使用指针,c 代码是一个数组的主要内容,如果未能解决你的问题,请参考以下文章
C++ 智能指针和指针到指针输出 API。模板化的“包装器”