使用Python的CFFI并排除系统头

2024-03-29 12:26:33 发布

您现在位置:Python中文网/ 问答频道 /正文

我正试图使用Python's CFFI来开发与用C编写的科学模型的Python绑定。CFFI文档有点少,我还停留在cdef阶段。在

到目前为止,我的流程遵循以下步骤:

  1. 预处理头文件:

    gcc -E -gcc -std=c99 -E -P src/my_c_interface.c -I./include/ -I../shared/include/ > header.txt

    这将生成一个文本文件,其中包含我的include/目录中头文件中包含的所有C声明。它还包括标准库的声明(我很肯定这就是我的问题所在)。header.txt看起来像这样(完整的页眉.txt是here):

    从系统标题开始:

    typedef float float_t;
    typedef double double_t;
    extern int __math_errhandling(void);
    extern int __fpclassifyf(float);
    extern int __fpclassifyd(double);
    extern int __fpclassifyl(long double);
    extern __inline __attribute__((__gnu_inline__)) __attribute__ ((__always_inline__)) int __inline_isfinitef(float);
    extern __inline __attribute__((__gnu_inline__)) __attribute__
    

    以标题中定义的片段结尾:

    FILE *LOG_DEST;
    void finalize_logging(void);
    void get_current_datetime(char *cdt);
    void get_logname(const char *path, int id, char *filename);
    
  2. 使用cffi解析预处理的头文件:

    import cffi
    
    ffi = cffi.FFI()
    
    with open('drivers/python/header.txt') as f_headers:
        ffi.cdef(f_headers.read())  # error is raised here
    
    ffi.compile()
    

    这将返回以下错误(完整回溯是here):

    /Users/me/anaconda/lib/python3.4/site-packages/cffi/cparser.py in convert_pycparser_error(self, e, csource)
        157         else:
        158             msg = 'parse error\n%s' % (msg,)
    --> 159         raise api.CDefError(msg)
        160 
        161     def parse(self, csource, override=False, packed=False):
    
    CDefError: cannot parse "extern __inline __attribute__((__gnu_inline__)) __attribute__ ((__always_inline__)) int __inline_isfinitef(float);"
    :10:17: before: __attribute_
    

鉴于我的处境,我有几个问题要问那些比我更熟悉cffi的人:

  1. 有没有可能让预处理器排除系统头?在
  2. 有没有人知道有比cffi文档中显示的更复杂的例子?现实世界的例子会很有帮助。在
  3. 看看上面的例子,我是否遗漏了一些重要的东西?在

Tags: gnutxthereinclude头文件inlineexternattribute
1条回答
网友
1楼 · 发布于 2024-03-29 12:26:33

这是一个有点笼统的答案:

虽然可以使用gcc -E方法并手动“修剪”结果,但不建议使用CFFI。相反,cdef()代码通常是以增量方式(根据需要添加函数)或从.h文件的编辑副本批量生成的。第一种方法在从手册页复制时效果最好;第二种方法适用于我们希望完全访问单个第三方库的情况。在

在所有情况下,您很可能无论如何都需要编辑.h文件:建议的方法是使用ffi.set_源(),并从cdef()中删除任何多余的声明,将其替换为...。例如,实际的.h文件可能包含声明#define FOOBAR 42,但不应依赖值42(例如,它可能在将来更改),因此cdef()应该接收#define FOOBAR ...。在

相关问题 更多 >