问题
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:
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). Theheader.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);
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:
- Is it possible to have the preprocessor exclude system headers?
- Is anyone aware of any examples that are more complex then those shown in the
cffi
docs? Real world examples would be helpful. - Looking at my example shown above, am I missing something major?
回答1:
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 ...
.
来源:https://stackoverflow.com/questions/31795394/using-pythons-cffi-and-excluding-system-headers