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?
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".