Это довольно длинный вопрос, но я надеюсь, что смогу его четко выразить.
Я пытаюсь обернуть библиотеку C ++, используя Python / C API. Основная библиотека, скажем, mylib , имеет свою собственную объектную систему (это что-то вроде интерпретатора для другого языка) и однозначно идентифицирует каждый объект в своей среде по Id . Он создает несколько потоков в своей функции init()
и выполняет разные операции в разных потоках (например, создает объекты в одном потоке и интерпретирует команды в другом потоке).
Сейчас я пытаюсь обернуть его в два уровня:
Я создал Dummy класс с Id объекта в mylib. Конструктор Dummy на самом деле вызывает функцию в mylib для создания нового объекта и сохранения его идентификатора. Другие методы в классе Dummy аналогичным образом вызывают эквивалентные функции в mylib. Это не использует Python / C API.
Я создал mylibmodule.cpp
, который использует API Python / C для предоставления функций, которые будут вызываться из интерпретатора Python.
Я вызываю init()
функцию mylib в PyMODINIT_FUNC init_mylib()
.
Я кодирую функции вроде:
static PyObject * py_new_Dummy(PyObject* self, PyObject *args){
// ... process arguments
return reinterpret_cast<PyObject*>(new Dummy);
}
Обратите внимание, что конструктор Dummy вызывает функции в mylib, которые выполняются в потоках, созданных с помощью pthreads.
Я собираю это в _mylib.so, и у меня есть mylib.py:
import _mylib
class MyClass(obj):
def __init__(self, *args)
self.__ptr = _mylib.py_new_Dummy()
Теперь к актуальной проблеме: я могу импортировать mylib в интерпретатор Python, но как только я попытаюсь:
a = MyClass(some_args)
Я получил ошибку сегментации. Обратный след GDB показывает
Программа получила сигнал SIGSEGV, ошибка сегментации.
__pthread_mutex_lock (mutex = 0x0) в pthread_mutex_lock.c: 50
Еще забавнее то, что если я отключаю создание нескольких потоков в коде mylib (все еще связанном с pthreads), я могу создавать экземпляры MyClass, но при выходе из интерпретатора Python я получаю нарушение сегментации.
Раздел «Тонкий лед» в документации по Python (http://docs.python.org/extending/) не просветил меня. Мне интересно, стоит ли мне использовать PyGILState_Ensure и PyGILState_Release для всех вызовов Python C / API в mylibmodule.cpp. Или это должен быть Py_BEGIN_ALLOW_THREADS и Py_END_ALLOW_THREADS
Кто-нибудь может помочь? Есть ли какая-либо определенная документация о том, как именно Python играет с pthreads?