ImportError from Cython при связывании внешней библиотеки C - PullRequest
6 голосов
/ 16 февраля 2012

Я пытаюсь повторить работу Флавиана Коэльо, ссылка здесь .Он использовал Cython и Научную библиотеку Gnu (GSL), чтобы значительно ускорить Python при генерировании случайных чисел.Когда я импортирую свой скомпилированный код Cython в Python (с помощью команды import cgibbs), я получаю следующую ошибку:

  ImportError: dlopen(./cgibbs.so, 2): Symbol not found: _gsl_rng_mt19937
  Referenced from: /Users/wesley/scratch/cython/cgibbs.so
  Expected in: dynamic lookup

Вы заметите, что жалоба на то, что символ _gsl_rng_mt19937 не можетбыть найденным.Функция, на которую я пытаюсь ссылаться, называется gsl_rng_mt19937 (без начального подчеркивания), и именно так она выглядит в моем файле .pyx.Я думаю, что Cython каким-то образом вызывает проблему, добавляя подчеркивание.

Чтобы упростить поиск неисправностей, я сократил код и разместил его ниже.Моя система: Mac OSX 10.7 (Lion) под управлением Python 2.7.2 (32-разрядная версия), gcc-4.0 (которую я использовал для компиляции библиотек GSL в 32-разрядной форме), GSL 1.15 и Cython v0.15.1.

Вот содержимое файла cgibbs.pyx:

#declaring external GSL functions to be used
cdef extern from "math.h":
   double sqrt(double)

cdef double Sqrt(double n):
   return sqrt(n)

cdef extern from "gsl/gsl_rng.h":
   ctypedef struct gsl_rng_type:
       pass
   ctypedef struct gsl_rng:
       pass
   gsl_rng_type *gsl_rng_mt19937
   gsl_rng *gsl_rng_alloc(gsl_rng_type * T)

cdef extern from "gsl/gsl_randist.h":
   double gamma "gsl_ran_gamma"(gsl_rng * r,double,double)
   double gaussian "gsl_ran_gaussian"(gsl_rng * r,double)


cdef gsl_rng *r = gsl_rng_alloc(gsl_rng_mt19937)

Ошибка исчезнет, ​​если я закомментирую последнюю строку моего cgibbs.pyx, но тогда я не смогу использовать внешнийбиблиотека ... Любое понимание, которое вы можете предложить, приветствуется.Спасибо!

Ответы [ 3 ]

4 голосов
/ 16 февраля 2012

Благодаря @ChuiTey я обнаружил, что otool и nm - это инструменты на Mac, которые могут делать то же, что objdump в Linux.С nm я обнаружил, что начальные подчеркивания являются частью имени символа в библиотеке libgsl.a.

Однажды я узнал, что компоновщик (в моем случае, ld) искал правильное имяБыло ясно, что он не выглядит в нужном месте.И вот как я узнал, что заголовочные файлы не знают расположение библиотек, на которые они ссылаются (Дух!) Мне просто нужно было добавить опцию -lgsl в команду, которая запускает компоновщик (для этого необходимо, чтобы libgsl.a былов каталоге, где ваш компоновщик ищет библиотеки - на моей машине это /usr/local/lib.)

Мне также пришлось переместить libgsl.dylib из /usr/local/lib, потому что он был скомпилирован для 64-битной платформы, и яЯ использую 32-битный Python.

Должен быть простой способ указать параметр компоновщика -lgsl при компиляции кода Cython с distutils или make-файлом;сейчас я просто запускаю gcc-4.0 дважды, чтобы скомпилировать и затем связать модуль.Мой рабочий процесс для компиляции модуля Cython из командной строки bash:

cython cgibbs.pyx
gcc-4.0 -m32 -I/Library/Frameworks/Python.framework/Versions/2.7/include/python2.7 -c cgibbs.c -o cgibbs.o
gcc-4.0 -bundle -undefined dynamic_lookup -lgsl -arch i386 -g cgibbs.o -o cgibbs.so

, который производит cgibbs.so, модуль Cython, который можно импортировать в Python 2.7.

2 голосов
/ 16 февраля 2012

Добавление подчеркивания к экспортируемым функциям называется искажение имени . В Windows соглашение cdecl добавляет одно подчеркивание (другие соглашения имеют более сложные схемы).

Возможно, вы неправильно указали соглашение о вызовах при сборке библиотеки GSL. Вы должны иметь возможность посмотреть, какие имена экспортируются, используя objdump .

Разве GSL не предоставляет упаковщики SWIG?

0 голосов
/ 27 марта 2013

Пожалуйста, взгляните на CythonGSL (https://github.com/twiecki/CythonGSL), если вы хотите использовать функции GSL в Cython.

...