Я создаю приложение Mac OS X, которое должно вставлять Python. Мое приложение является технически связкой (т.е. Его основным исполняемым файлом является MH_BUNDLE); это плагин для другого приложения. Я бы хотел, чтобы он вставлял Python статически, но хочу иметь возможность динамически загружать расширения.
Я сделал следующее: я включил целую библиотеку (-force_load path/to/libpython2.7.a
), также повторно экспортировал все символы Python (-exported_symbol_list path/to/list
) и добавил -u _PyMac_Error
, который я получил с помощью этот справочник по связям. Сам пакет загружается отлично, все работает на внутреннем Python-коде, но он терпит неудачу, когда он пытается импортировать динамическую библиотеку (time.so
) со следующим сообщением:
Traceback (most recent call last):
...
ImportError: dlopen(/<stripped>/time.so, 2): Symbol not found: _PyExc_OverflowError
Referenced from: /<stripped>/time.so
Expected in: dynamic lookup
Этот символ является частью API Python, и он уже должен быть в моем пакете. Я могу проверить это:
nm -g Build/Debug/pyfm | grep _PyExc_OverflowError
00172884 D _PyExc_OverflowError
0019cde0 D _PyExc_OverflowError
(Он указан дважды, потому что у меня две архитектуры: i386 и ppc).
time.so
ничего не ссылается, что, как я понимаю, по дизайну:
otool -L "/<stripped>/time.so"
/<stripped>/time.so (architecture ppc):
/usr/lib/libgcc_s.1.dylib (compatibility version 1.0.0, current version 1.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 88.3.11)
/<stripped>/time.so (architecture i386):
/usr/lib/libgcc_s.1.dylib (compatibility version 1.0.0, current version 1.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 88.3.11)
Моя проблема похожа на this, но это наоборот: я связываю Python статически, а другой плакат связывает его динамически (наши платформы тоже разные). Для него статическая связь решала проблему.
Почему он не находит символ?
Обновить. Я подозреваю, что это происходит, потому что основное приложение загружает свои плагины (и, таким образом, мой пакет) с помощью RTLD_LOCAL
.