2016-04-29 4 views
0

У меня есть некоторые определения cffi, распространяемые по нескольким подкаталогам проектов - каждый файл cffi определяет типы и функции, каждый из которых компилируется в файл _<package>.py для загрузки. В окончательном приложении I ffi.include() верхние уровни (которые рекурсивно ffi.include() нижнего уровня) и сгенерировать компиляцию файла _<app>.py для загрузки в приложение. Я использую один экземпляр ffi для загрузки файлов *.so. Однако я не вижу, как это загружает распространенные файлы _<package>.py в приложение. Я получаю следующее сообщение об ошибке (пример):Несколько определений ffi с ffi.include (...)

два отдельных файла FFI определение, root/get/ffi_getA.py и root/use/ffi_useA.py

, какие функции C являются частью одной и той же библиотеки, скажем libA.so.

ffi_getA.py:

from cffi import FFI 
ffi=FFI() 
ffi.set_source("getA",None) 
ffi.cdef(''' 
typedef ... A;  // type also used in another ffi definition. 
const A* get_A(); 
''') 

ffi_useA.py:

from cffi import FFI 
ffi=FFI() 
ffi.set_source("useA",None) 
from root.get import ffi_getA 
ffi.include(ffi_getA.ffi)   # makes available type A 
ffi.cdef(''' 
const void* use_A(const A*); // use type A 
''') 

В приложении:

from root.get import getA # compiled ffi 
from root.use import useA # compiled ffi 

libAget = getA.ffi.dlopen("libA.so") 
libAuse = useA.ffi.dlopen("libA.so") 

a = libAget.getA() 

libAuse.useA(a) # !!! mixing !!!, a is indeed of type A ... 
       # ... but from a different ffi instance. 

Это смешение не будет работать, так что вопрос:

Как получить доступ/загрузить функции cdef, распространяемые по различным скомпилированным объектам ffi через общий/единственный объект ffi?

+0

Похоже, cffi не делает то, что вы ожидаете от него.Но вам нужно придумать конкретный пример, чтобы мы могли помочь вам (или исправить cffi :-) –

+1

@stustd вместо того, чтобы редактировать ваш вопрос, чтобы поделиться найденным вами решением, отправьте его как отдельный ответ и примите его , Вы должны объяснить это немного больше. –

ответ

0

Решение

Чтобы построить интерфейс cffi из одного экземпляра FFI все должно начинаться с корня питона CDEF строитель сценария. Из этого сценария экземпляр ffi импортируется и расширяется в следующем скрипте строителя, который зависит от типов, определенных в предыдущем сценарии построителя; и так далее. В основном,

В foo.py:

ffi = cffi.FFI() 
ffi.cdef("...") 

В bar.py:

from foo import ffi 
ffi.cdef("...") 

Таким образом, существует только один экземпляр FFI. (Вероятно, следует избегать так называемых «зависимостей импорта алмазов» между файлами cffi/cdef, чтобы избежать дублирования определений).

Импорт экземпляров ffi на уровне модуля имеет решающее значение для того, чтобы функции декоратора имели доступ к определенным типам. (Ретроспективно это тривиально, но сначала я импортировал на уровне buildg экземпляра и использовал отдельный экземпляр для декораторов - это работало до тех пор, пока мне не нужны пользовательские определенные типы ...).

И, наконец, в этой процедуре вам не понадобится ffi.include (...) - «включение» осуществляется через импорт. Кроме того, поскольку источник генерируется только в сценарии окончательного построителя, команды ffi.set_source (..) в подстроках должны перемещаться под «if __name __ ==» __ main__ »перед ffi.compile (...). (Таким образом, индексы будут генерировать источник при вызове локально, например, для целей тестирования.)

Смежные вопросы