Мне нужно написать оболочку Python2 для проприетарной библиотеки, состоит из нескольких файлов .h (я сделал один большой), связки .dll и одного .lib файла, чтобы связать все эти вещи.
Я думаю, что мне нужен уровень API, потому что все это `typedef ‘в .h файлах
Скрипт для создания оболочки: 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)
Это работает без ошибок Creating library .\Release\_wrapper.lib and object .\Release\_wrapper.exp
Но, например,
from _wrapper import ffi, lib
lp_api = ffi.new('ScadAPI *')
r = lib.ApiCreate(lp_api)
Сбой с
lp_api = ffi.new('ScadAPI *')
ffi.error: undefined type name
ScadAPI *
ScadAPI
определяется как
struct APIHandle_tag;
typedef APIHandle_tag * ScadAPI;
в ScadWrapper.h
Ты никогда не звонишь ffibuilder.cdef()
, Вот почему lib
Объект пуст: он не знает ни о каком типе или функции.
Извините за краткость. Я хочу сказать, что основы объясняются на http://cffi.readthedocs.io/en/latest/overview.html. Следуя «реальному примеру», идея состоит в том, чтобы писать в cdef () только те части, которые вам интересны, одну функцию за другой и объявления типов с подходящим использованием ...;
, Каждая функция или тип, который вы пишете в cdef (), становятся доступны для вызова (через lib.the_function_name()
) или для операций ffi (ffi.new()
, так далее.).
Существуют различные подходы к cffi (непосредственно не документированные или не поддерживаемые), которые пытаются сразу открыть всю большую библиотеку, не требуя какой-либо отдельной функции, какой бы маленькой она ни была. Идея состоит в том, чтобы извлечь из файла .h (возможно, предварительно обработанный gcc -E
) что-то, что может быть принято cdef (). Недостаток, особенно если вы используете gcc -E
является то, что результат может работать только на вашей конкретной ОС. Более того, такой подход появляется быстрее, но часто это не так: кажется, что он избегает работы для каждой функции, но это никогда не так, потому что, если вы собираетесь использовать эту функцию где-то, тогда вам потребуется время, чтобы написать вызов этой функции. тем не мение.
Других решений пока нет …