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

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

class Value
{
    public:

    Value();
    ~Value();

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

У меня есть модуль повышения Python:

#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 из python.

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

Что я делаю не так?

1 Ответ

0 голосов
/ 01 ноября 2018

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

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

...