Search code examples
c#cswig

let swig handle a c struct hack (__flexarray)


I'm trying to create c# wrapper code for linux' inotify and inotifywait.

Problem is that swig isn't able to handle the flex array struct hack used in inotify
swig version is 4.0.2 and inotify.h is from glib-headers 2.17-324 (according to 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
}

According to What is __flexarr and how/why do c programmers use it? this is a struct hack and valid C99.

My swig-interface file looks like

%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"

when I call swig like swigg -csharp -I/usr/include/inotifytools -I/usr/incldue/sys -Wall inotifybinding.i it fails with the error Syntax error - possibly a missing semicolon and points to the line with the struct hack.

I then thought maybe I can just create my own version of inotify_event and ignore the declaration from inotify.h like

%{
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

Unfortunately the error perists and I need this struct because otherwise important functions like inotifytools_next_event return some kind of cptr which I don't know how to handle with C#.

I thought the ignore would basically just remove every declaration named inotify_event from the wrapper code but it seems that the %includes are validated before the %ignore is triggered.

Is there a way I can get inotify_event properly created in my wrapper code?

EDIT:: also the newest swig version doesn't work


Solution

  • SWIG doesn't understand a lot of compiler-specific things, such as __cdecl and __stdcall on Windows, but if you look at Lib\windows.i in the SWIG installation, you'll see the preprocessor is used to remove them, e.g. #define __cdecl.

    I don't have a way to verify this, but you might get away with the following to turn that unknown-to-SWIG compiler option to a more standard declaration:

    %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"