使用Python的CFFI和排除系统头 [英] Using Python's CFFI and excluding system headers

查看:973
本文介绍了使用Python的CFFI和排除系统头的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图使用 Python的CFFI 开发Python绑定到C.写的CFFI文档中科学模型是有点稀疏,我被困在 CDEF 阶段。

我的过程到现在一直遵循下列步骤进行:


  1. preprocess的头文件:

    gcc的-E -gcc -std = C99 -E -P的src / my_c_interface.c -I./include/ -I ../共享/有/> header.txt

    这会产生一个包括所有包含在头文件在我的包含/ 目录C声明的文本文件。它还包括标准库声明(我是pretty肯定这是我的问题的根源)。在 header.txt 看起来像这样(完整header.txt是的这里):

    与系统头的东西开始:

     的typedef浮动则float_t;
    双的typedef DOUBLE_T;
    EXTERN INT __math_errhandling(无效);
    EXTERN INT __fpclassifyf(浮动);
    EXTERN INT __fpclassifyd(双);
    EXTERN INT __fpclassifyl(长双);
    的extern __inline __attribute __((__ gnu_inline__))__attribute__((__always_inline__))INT __inline_isfinitef(浮动);
    的extern __inline __attribute __((__ gnu_inline__))__attribute__

    和在我的头文件中定义片结尾:

      FILE * LOG_DEST;
    无效finalize_logging(无效);
    无效get_current_datetime(字符* CDT);
    无效get_logname(为const char *路径,INT ID,字符*文件名);


  2. 使用 CFFI 来解析preprocessed头文件:

     进口CFFIFFI = cffi.FFI()开放('司机/蟒蛇/ header.txt')为f_headers:
        ffi.cdef(f_headers.read())#错误在这里提出ffi.compile()

    这将返回以下错误(全回溯是这里):

      /Users/me/anaconda/lib/python3.4/site-packages/cffi/cparser.py在convert_pycparser_error(个体经营,电子,csource)
        157其他:
        158味精='解析错误。\\ n%s'的%(味精,)
    - > 159升api.CDefError(MSG)
        160
        161高清解析(个体经营,csource,倍率=假,装= FALSE):CDefError:无法解析外部__inline __attribute __((__ gnu_inline__))__attribute__((__always_inline__))INT __inline_isfinitef(浮动);
    :10:17:前:__attribute_


鉴于我在哪里,我对那些更熟悉CFFI比我几个问题


  1. 是否有可能有preprocessor排除系统头?

  2. 是任何人都意识到这是比较复杂的,然后那些在 CFFI 文档表现出任何的例子吗?现实世界中的例子将是有益的。

  3. 看着我的例子如上图所示,我失去了什么专业?


解决方案

这是一个有些通用的答案:

虽然可以使用的gcc -E 办法和手动调整的结果,所以不推荐的方式来使用CFFI。相反,CDEF()code通常是从.h文件的编辑副本或者做增量(根据需要添加的功能),或散装。从手册页复印时,第一种方法效果最好;第二种方法是,我们要到一个第三方库的完全访问权限的情况下。

在所有的情况下,它很可能,你需要反正编辑.h文件中:建议的方法是使用ffi.set_source(),并从CDEF删除()来说是多余的任何声明,以取代他们 ... 。例如,实际的.h文件中可能包含的声明的#define FOOBAR 42 ,但应该42不能依赖值(例如,它可能会在未来改变),因此,在CDEF()而应接受的#define FOOBAR ...

I'm trying to use Python's CFFI to develop Python bindings to a scientific model written in C. The CFFI documentation is a little sparse and I'm stuck at the cdef stage.

My process up to now has followed these steps:

  1. Preprocess the header files:

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

    This produces a text file that includes all the C declarations included in the header files in my include/ directories. It also includes declarations for standard libraries (I'm pretty sure this is where my problem is coming from). The header.txt looks something like this (the full header.txt is here):

    Beginning with system header stuff:

    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__
    

    and ending with pieces defined in my headers:

    FILE *LOG_DEST;
    void finalize_logging(void);
    void get_current_datetime(char *cdt);
    void get_logname(const char *path, int id, char *filename);
    

  2. Use cffi to parse the preprocessed header files:

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

    This returns the following error (full traceback is 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_
    

Given where I'm at, I have a few questions for those more familiar with cffi than I:

  1. Is it possible to have the preprocessor exclude system headers?
  2. Is anyone aware of any examples that are more complex then those shown in the cffi docs? Real world examples would be helpful.
  3. Looking at my example shown above, am I missing something major?

解决方案

This is a somewhat generic answer:

While it is possible to use the gcc -E approach and manually "trim" the result, it is not the recommended way to use CFFI. Instead, the cdef() code is usually made either incrementally (adding functions as needed) or in bulk from an edited copy of the .h file. The first approach works best when copying from man pages; the second approach is for the case where we want complete access to a single 3rd-party library.

In all cases, it is very likely that you need to edit the .h file anyway: the recommended approach is to use ffi.set_source(), and remove from the cdef() any declarations that are superfluous, replacing them with .... For example, the actual .h file may contain the declaration #define FOOBAR 42, but the value 42 should not be relied upon (e.g. it could change in the future), so the cdef() should rather receive #define FOOBAR ....

这篇关于使用Python的CFFI和排除系统头的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆