Search code examples
socketspython-cffi

Using standard library headers with CFFI


I am using Python and CFFI to write some unit tests for a library that I have written in C, this library involves socket programming on Linux. The .c file is compiled into a shared library and then loaded using ffi.dlopen().

Naturally the struct sockaddr_in structure is used which is defined in netinet/in.h, and in my case it is used within another structure.

typedef struct sDeviceSockAddr
{
    int sockfd;
    struct sockaddr_in deviceAddr;  
} tDeviceSockAddr;

I am using ffi.cdef() to define this structure. Running the unit test returns the (kind of expected) following error :

TypeError: field 'tDeviceSockAddr.DeviceAddr' has ctype 'struct sockaddr_in' of unknown size

My first thought was how do I load the whole netinet/in.h, but being new to CFFI, I am not sure that this is the way to go.

Is it possible to load netinet/in.h correctly? if so, how? If not, what is the way to do this?


Solution

  • If you are using ffi.dlopen(), then you're out of luck. The only way to do that would be to declare explicitly the struct sockaddr_in in your cdef, maybe by copy-pasting bits of the Linux headers, assuming you're on Linux---and then of course the result is not portable.

    You may want instead of look into using a proper ffibuilder approach, which require a compiler at installation time but lets you use any external include file. It's the mode described at https://cffi.readthedocs.io/en/latest/overview.html#main-mode-of-usage. In that mode you would write struct sockaddr_in { ...; }; in the cdef(), with literally dot-dot-dot, if you don't need the content of struct sockaddr_in from Python; or if you do you can include the fields that you need, but be sure to also write "...;", which means "this is a partial declaration; please use the real header to fix the order of fields and total size of the structure".