Here's my preprocessor section in my C++ code which I want to generate SWIG bindings.
#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__FreeBSD_kernel__) \
|| defined(__OpenBSD__)
#include <machine/endian.h>
#endif
#if defined(__linux__) || defined(__CYGWIN__) || defined(__GNU__) || \
defined(ANDROID)
#include <endian.h>
#endif
#ifdef __MINGW32__
#include <sys/param.h>
#endif
#ifdef _MSC_VER
/* _MSVC lacks BYTE_ORDER and LITTLE_ENDIAN */
#define LITTLE_ENDIAN 0x0001
#define BYTE_ORDER LITTLE_ENDIAN
#endif
#if !defined(BYTE_ORDER) || !defined(LITTLE_ENDIAN)
#error No byte order defined
#endif
#if BYTE_ORDER == LITTLE_ENDIAN
# define HIOFFSET 1
# define LOWOFFSET 0
#else
# define HIOFFSET 0 /* word offset to find MSB */
# define LOWOFFSET 1 /* word offset to find LSB */
#endif
But when I try to generate SWIG bindings using the swig
command, I get the following error:
Error: CPP #error "No byte order defined". Use the -cpperraswarn option to continue swig processing.
It seems when SWIG tries to generate the bindings, <machine/endian.h>
is not being included for some reasons.
How can I fix this error? Do I need to add anything to the SWIG interface file?
I'm using macOS 10.14.4.
ADDED: Here's what my SWIG interface file looks like.
%module pd
%{
#include "myBindings.h"
%}
%include "myBindings.h"
As you can see there's nothing special in it.
And I generate the bindings using the following command:
swig -c++ -lua -fcompact -fvirtual -I../../../libs/openFrameworks myBindings.i && mv myBindings_wrap.cxx myBindings.cpp
Then I get the above mentioned error.
Even when I just leave #include <machine/endian.h>
it still generates the same error. (No byte order defined
)
The reason SWIG is failing is because it doesn't normally recurse into include files when you %include
a file to wrap its interface, so the definitions defined in <machine/endian.h>
are not processed.
There are a number of options to remedy this:
Use -cpperraswarn
and ignore the error as suggested. SWIG will process the #if incorrectly, but it is the compiler that builds the value. SWIG will still expose the HIOFFSET
and LOWOFFSET
values in the wrapper, and the value will be correct.
%include <machine/endian.h>
explicitly. That may or may not work correctly depending on the content of the file, and may expose more variables in the SWIG wrapper than intended.
Use -includeall
with SWIG to explicitly recurse into all #include files. This is normally not wanted as SWIG will attempt to wrap all definitions. For example, you'd get everything in #include <stdio.h>
if present.
Explicitly define BYTE_ORDER
and/or LITTLE_ENDIAN
in the SWIG .i file to work around the issue.
Here's a couple of examples:
%module test
%{
#include "test.h"
%}
%include "test.h"
SWIG generates the warning, and the result is only HIOFFSET
and LOWOFFSET
are defined, but they are correct for my little-endian machine even with the error from SWIG. The compiler still processed the definition correctly.
>>> import test
>>> dir(test)
['HIOFFSET', 'LOWOFFSET', 'SWIG_PyInstanceMethod_New', '__builtin__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', '_swig_getattr', '_swig_property', '_swig_repr', '_swig_setattr', '_swig_setattr_nondynamic', '_swig_setattr_nondynamic_method', '_test']
>>> test.HIOFFSET
1
In this case I have a Windows machine so I simulated the problem by creating an msvc_endian.h
file and defining BYTE_ORDER
and LITTLE_ENDIAN
in it.
test.h was modified to use the following snippet:
#ifdef _MSC_VER
#include "msvc_endian.h"
#endif
test.i explicitly processed the header:
%module test
%{
#include "test.h"
%}
%include "msvc_endian.h"
%include "test.h"
msvc_endian.h
#define LITTLE_ENDIAN 0x0001
#define BYTE_ORDER LITTLE_ENDIAN
SWIG now has no warning and the result is still correct, but due to processing the sub-header LITTLE_ENDIAN
and BYTE_ORDER
were also exposed as values in the wrapper:
>>> import test
>>> dir(test)
['BYTE_ORDER', 'HIOFFSET', 'LITTLE_ENDIAN', 'LOWOFFSET', 'SWIG_PyInstanceMethod_New', '__builtin__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', '_swig_getattr', '_swig_property', '_swig_repr', '_swig_setattr', '_swig_setattr_nondynamic', '_swig_setattr_nondynamic_method', '_test']
>>> test.HIOFFSET
1