让 swig 处理 c struct hack (__flexarray)

let swig handle a c struct hack (__flexarray)

我正在尝试为 linux' inotifyinotifywait.

创建 c# 包装器代码

问题是 swig 无法处理 inotify
中使用的 flex 数组结构 hack swig 版本是 4.0.2,inotify.h 来自 glib-headers 2.17-324(根据 rpm -q --whatprovides /usr/include/sys/inotify.h

struct inotify_event
{
   int wd;
   uint32_t mask;
   uint32_t cookie;
   uint32_t len;
   char name __flexarray; // <- this fails
}

根据 What is __flexarr and how/why do c programmers use it?,这是一个 struct hack 和有效的 C99。

我的 swig-interface 文件看起来像

%module mymodule
%{
#include "/usr/includes/sys/inotify.h"
#include "/usr/includes/inotifywait/inotifytools.h"
};

%include "/usr/includes/sys/inotify.h"
%include "/usr/includes/inotifywait/inotifytools.h"

当我像 swigg -csharp -I/usr/include/inotifytools -I/usr/incldue/sys -Wall inotifybinding.i 那样调用 swig 时,它失败并显示错误 Syntax error - possibly a missing semicolon 并指向带有结构 hack 的行。

然后我想也许我可以创建自己的 inotify_event 版本并忽略来自 inotify.h 的声明,例如

%{
struct inotify_event
{
   int wd;
   uint32_t mask;
   uint32_t cookie;
   uint32_t len;
   char name []; // <- should be the same as with __flexarray
}
// the #includes
};

%ignore inotify_event
// the %includes

不幸的是,错误仍然存​​在,我需要这个结构,因为其他重要的功能,如 inotifytools_next_event return 某种 cptr 我不知道如何用 C# 处理。

我认为忽略基本上只会从包装代码中删除名为 inotify_event 的每个声明,但似乎在触发 %ignore 之前验证了 %includes。

有没有办法在我的包装代码中正确创建 inotify_event

编辑::最新的 swig 版本也不起作用

SWIG 不理解很多特定于编译器的东西,例如 Windows 上的 __cdecl__stdcall,但是如果您查看 Lib\windows.i SWIG 安装,您会看到预处理器用于删除它们,例如#define __cdecl.

我没有办法验证这一点,但您可以通过以下方法将未知的 SWIG 编译器选项转换为更标准的声明:

%module mymodule
%{
// included normally here
#include "/usr/includes/sys/inotify.h"
#include "/usr/includes/inotifywait/inotifytools.h"
};

#define __flexarray []    // turn "char name __flexarray;" into "char name[];"
%include "/usr/includes/sys/inotify.h"
%include "/usr/includes/inotifywait/inotifytools.h"

Mark Tolonens 解决方案确实解决了我最初的问题,但出现了语法错误等其他问题。 分别弹出不是因为 Mark Tolonens 的建议破坏了某些东西,而是因为它解决了第一个问题,而 SWIG 只是偶然发现了下一个问题。

经过一番挖掘后,我添加了以下 header 这解决了我所有的问题。

%module mymodule
%{
#include "/usr/includes/sys/inotify.h"
#include "/usr/includes/inotifywait/inotifytools.h"
};

%include "/usr/includes/sys/cdefs.h" // <- add this line here
%include "/usr/includes/sys/inotify.h"
%include "/usr/includes/inotifywait/inotifytools.h"

通过这一行,SWIG 为 inotify_event 生成了一个 c# class,一些快速测试证实了它的工作。

或者您可以自己进行封送处理,但是您必须处理 c# 等中的内存分配。