Python boost to-Python конвертер для класса уже зарегистрирован второй метод преобразования игнорируется

У меня есть следующий класс (это было упрощено):

class Value
{
public:

Value();
~Value();

void setValue(int value);
void setValue(double value);
}

У меня есть модуль Python Boost:

#include <boost/python.hpp>
#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
#include <boost/python/suite/indexing/map_indexing_suite.hpp>

BOOST_PYTHON_MODULE(py_classes)
{
typedef std::vector<Value> VectorClass;

boost::python::type_info infoVectorValue = boost::python::type_id<VectorClass>();

const boost::python::converter::registration* regVectorValue = boost::python::converter::registry::query(infoVectorValue);

if (regVectorValue == NULL || (*regVectorValue).m_to_python == NULL) {
class_<VectorClass>("std_vector_value")
.def(vector_indexing_suite<VectorClass>());
}
}

Сценарий Python вызывается из библиотеки dll и использует контейнер из pyd. py_classes, Когда dll-библиотека вызывается впервые std_vector_value Тип используется без проблем.
Когда я перезагружаю dll-библиотеку внутри исполняемого файла, я получаю следующее предупреждение:

RuntimeWarning: to-Python converter for class
boost::python::detail::container_element<class std::vector<class Value,class std::allocator<class Value> >,
unsigned __int64,class boost::python::detail::final_vector_derived_policies
<class std::vector<class Value,
class std::allocator<class Value> >,0> >
already registered; second conversion method ignored.
return f(*args, **kwds)

Итак, это значит:

  • Когда dll-библиотека загружается в первый раз, конвертер to-python регистрируется нормально и скрипт Python может использовать std_vector_value тип.
  • Когда библиотека dll перезагружается (FreeLibrary а также LoadLibrary функции), конвертер to-python, пытающийся зарегистрироваться еще раз и проверяющий, зарегистрирован ли он, говорит, что он уже зарегистрирован, но я не могу использовать std_vector_value тип из питона.

И эта ситуация появляется только для контейнерных классов (если я использую std::vector или же std::map — как правило, если я использую vector_indexing_suite или же map_indexing_suite), для класса Value это предупреждение не появляется.

Что я делаю неправильно?

0

Решение

Проблема была следующая: boost python загружался из одного exe-процесса, но разными DLL-библиотеками. Это означает, что у меня было 3 DLL-библиотеки, которые выполняли скрипты Python.
Типы повышения Python работали без проблем до тех пор, пока DLL-библиотеки не были перезагружены (вызывая FreeLibrary и LoadLibrary внутри процесса без перезапуска процесса).
Python boost имеет статическую переменную register (register — это имя этой переменной) хранит ссылки на типы надстроек Python.
Когда исполняемый файл запускается, ссылки на типы добавляются в статическую переменную register,
Итак, эта проверка работает нормально:

boost::python::type_info infoVectorValue = boost::python::type_id<VectorClass>();
const boost::python::converter::registration* regVectorValue = boost::python::converter::registry::query(infoVectorValue);
if (regVectorValue == NULL || (*regVectorValue).m_to_python == NULL) {

Но когда DLL-библиотеки выгружаются, ссылки на эти типы форсирования Python остаются внутри статической переменной. register и они приводят к адресам библиотек DLL, которые были освобождены. Это означает, что когда библиотека загружается снова, проверка типов получает ссылку на нужный тип (VectorClass в моем примере) без проблем, но эта ссылка уже сломана.

Итак, решение этой проблемы состоит в том, чтобы статически связать библиотеку boost python с каждой DLL-библиотекой — каждая DLL-библиотека имеет свою статическую переменную register и повысить типы Python
ссылки создаются для каждой DLL-библиотеки и, когда DLL-библиотека выгружается, register Переменная уничтожена для этой DLL.

0

Другие решения

Других решений пока нет …