0

I need to write Python2 wrapper for proprietary library, consists of few .h files (I made one big), bunch of .dll and one .lib file to link all this stuff.

I think I need API level, because of all this `typedef' in .h files

Script to create wrapper: build_wrapper.py

from cffi import FFI
import setuptools

ffibuilder = FFI()
ffibuilder.set_unicode(enabled_flag=True)
with open(os.path.join(curdir, 'include', 'ScadWrapper.h'), 'r') as f:
    source = f.read()

ffibuilder.set_source('_wrapper', source,
                      extra_link_args=[r'C:\Documents\python\pyScadApi\pyScadApi\include\SCADAPIX.lib', ],
                      source_extension='.cpp')


if __name__ == '__main__':
    ffibuilder.compile(verbose=True)

This runs without errors Creating library .\Release\_wrapper.lib and object .\Release\_wrapper.exp

But, for example,

from _wrapper import ffi, lib

lp_api = ffi.new('ScadAPI *')
r = lib.ApiCreate(lp_api)

Fails with

lp_api = ffi.new('ScadAPI *')
ffi.error: undefined type name
ScadAPI *

ScadAPI defined as

struct APIHandle_tag;
typedef APIHandle_tag * ScadAPI;

in ScadWrapper.h

alfnak
  • 1
  • 1

1 Answers1

1

You are never calling ffibuilder.cdef(). That's why the lib object is empty: it doesn't know about any type or function.


Sorry about being brief. My point is that the basics are explained on http://cffi.readthedocs.io/en/latest/overview.html. Following the "real example", the idea is to write in the cdef() only the pieces that are interesting to you, one function after the other, and the type declarations with suitable usage of ...;. Every function or type you write in cdef() becomes available for call (via lib.the_function_name()) or for ffi operations (ffi.new(), etc.).

There are different approaches to cffi (not directly documented or supported) that try to expose a whole large library at once, without needing any function-by-function work, however small that is. The idea is to extract from a .h file (possibly preprocessed by gcc -E) something that can be accepted by the cdef(). The drawback, particularly if you use gcc -E, is that the result is likely to work only on your exact OS. Moreover, such an approach appears faster but often isn't: it seems to avoid a per-function work, but that's never true, because if you are going to use that function somewhere, then you'll take time to write that function call anyway.

Armin Rigo
  • 12,048
  • 37
  • 48
  • Sorry for a loooong answer. If I pass contents of the .h file to cdef() I have a bunch of errors about syntax. Does cdef() allow C++ syntax? Maybe I have to eliminate all this crazy typedefs and use standard C types? – alfnak Feb 10 '17 at 07:17
  • @alfnak cdef only allows C definitions. No C++, No includes, no pragmas etc. Just plain definitions with occasional "..." hint to fill up definitions you don't need. – psiyumm Jan 29 '18 at 18:12