Símbolo indefinido al importar un módulo de cython haciendo uso de otro módulo de cython

Estoy trabajando para envolver un conjunto de funciones de C usando Cython en un módulo. Me gustaría poder importar este primer módulo en proyectos subsiguientes basados ​​en Cython, pero me estoy topando con un problema de ‘símbolo indefinido’ al importar los módulos derivados en un script de python.

Considere el siguiente ejemplo de trabajo mínimo de dos módulos desarrollados en directorios separados:

# exModA wraps the functions provided in exModAFxn.c exModA/ __init__.pxd __init__.py exModAFxn.c exModA.pyx setup.py # exModB attempts to use the cdef functions from exModA exModB/ __init__.py exModB.pyx setup.py # The test script attempts to make use of exModB test.py 

exModA / __ init __. pxd:

 cdef extern void myCMessage() 

exModA / __ init__.py:

 from exModA import * 

exModA / exModAFxn.c:

 #include  void myCMessage() { printf( "This is a test!\n" ); } 

exModA / exModA.pyx:

 cdef extern from "exModAFxn.c" : void myCMessage() # Use myCMessage in a python function def foo() : myCMessage() 

exModA / setup.py:

 from distutils.core import setup, Extension from Cython.Build import cythonize setup( name = 'exModA', ext_modules = cythonize( ['exModA/exModA.pyx'] ), ) 

exModB / __ init__.py:

 from exModB import * 

exModB / exModB.pyx:

 cimport exModA # Use a cdef function from exModA in a python function def bar() : exModA.myCMessage() 

exModB / setup.py:

 from distutils.core import setup, Extension from Cython.Build import cythonize setup( name = 'exModB', ext_modules = cythonize( ['exModB/exModB.pyx'] ), ) 

Se llama al script test.py después de comstackr los dos módulos de cython.

 python extModA/setup.py build_ext --inplace python extModB/setup.py build_ext --inplace 

test.py:

 import exModA exModA.foo() # successfully prints message import exModB # raises ImportError: undefined symbol: myCMessage exModB.bar() # we never get to this line :( 

La impresión exitosa del mensaje desde la función exModA.foo me sugiere que myCMessage está de hecho disponible, pero no se encuentra cuando se importa exModB. Sé que este problema desaparece si fusiono exModA y exModB en un solo proyecto, pero me gustaría evitar ese enfoque si es posible. Estoy tratando de exponer un conjunto común de envoltorios para una biblioteca de C para su uso en diferentes aplicaciones

Pude hacer que esto funcionara haciendo lo siguiente:

Primero, especifique la biblioteca exModA para enlazar en su archivo exModB/setup.py la siguiente manera:

 from distutils.core import setup, Extension from Cython.Build import cythonize ext = Extension('exModB/exModB', sources=['exModB/exModB.pyx'], libraries=['exModA'], library_dirs=['/home/MyFolder/exModA'], runtime_library_dirs=['/home/MyFolder/exModA'] ) setup(name='exModB', ext_modules = cythonize(ext)) 

(En lugar de especificar un directorio de biblioteca en tiempo de ejecución, recomiendo mover exModA.so a una carpeta en la ruta de búsqueda de su biblioteca).

También tuve que cambiar el nombre de exModA.so a libexModA.so para que gcc pudiera encontrarlo. Haga esto después de exModA.so , pero antes de exModB.so :

 python exModA/setup.py build_ext --inplace cp exModA/exModA.so exModA/libexModA.so python exModB/setup.py build_ext --inplace 

Probablemente querrá modificar esto, pero debería comenzar.