生成 SWIG 绑定时不能包含 <endian.h>

Cannot include <endian.h> when generating SWIG bindings

这是我要生成 SWIG 绑定的 C++ 代码中的预处理器部分。

#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

但是当我尝试使用 swig 命令生成 SWIG 绑定时,出现以下错误:

Error: CPP #error "No byte order defined". Use the -cpperraswarn option to continue swig processing.

似乎当 SWIG 尝试生成绑定时,<machine/endian.h> 由于某些原因未被包括在内。

我该如何解决这个错误?我需要向 SWIG 接口文件添加任何内容吗?

我使用的是 macOS 10.14.4。


已添加:这是我的 SWIG 界面文件的样子。

%module pd
%{
    #include "myBindings.h"
%}
%include "myBindings.h"

如您所见,它没有什么特别之处。

然后我使用以下命令生成绑定:

swig -c++ -lua -fcompact -fvirtual -I../../../libs/openFrameworks myBindings.i && mv myBindings_wrap.cxx myBindings.cpp

然后我得到上面提到的错误。 即使我刚离开 #include <machine/endian.h> 它仍然会产生相同的错误。 (No byte order defined)

SWIG 失败的原因是,当您 %include 一个文件来包装其接口时,它通常不会递归到包含文件中,因此不会处理 <machine/endian.h> 中定义的定义。

有许多选项可以解决此问题:

  1. 使用-cpperraswarn并按建议忽略错误。 SWIG 将错误地处理 #if,但构建值的是 编译器 。 SWIG 仍会在包装器中公开 HIOFFSETLOWOFFSET 值,并且该值将是正确的。

  2. %include <machine/endian.h> 明确。这可能会或可能不会正常工作,具体取决于文件的内容,并且可能会在 SWIG 包装器中公开比预期更多的变量。

  3. -includeall 与 SWIG 一起使用以显式递归到所有 #include 文件中。这通常是不需要的,因为 SWIG 将尝试包装所有定义。例如,如果存在 #include <stdio.h>,您将获得所有内容。

  4. 在 SWIG .i 文件中明确定义 BYTE_ORDER and/or LITTLE_ENDIAN 以解决此问题。

这里有几个例子:

--cpperraswarn 解决方案:

test.i

%module test

%{
#include "test.h"
%}

%include "test.h"

SWIG 生成警告,结果只定义了 HIOFFSETLOWOFFSET,但它们对于我的 little-endian 机器是正确的,即使有来自 SWIG 的错误。编译器仍然正确地处理了定义。

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

%include endian.h 解决方案:

在这种情况下,我有一台 Windows 机器,所以我通过创建一个 msvc_endian.h 文件并在其中定义 BYTE_ORDERLITTLE_ENDIAN 来模拟问题。

test.h 已修改为使用以下代码段:

#ifdef _MSC_VER
#include "msvc_endian.h"
#endif

test.i 明确处理了 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 现在没有警告,结果仍然正确,但由于处理 sub-header LITTLE_ENDIANBYTE_ORDER 也作为值暴露在包装器中:

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