Сбой при вызове от boost :: python :: exec (что угодно)

Я пытаюсь реализовать некоторые элементы Python в своей программе, и я решил использовать Boost :: Python, поэтому я скомпилировал его в соответствии с инструкциями, используя bjam, используя mingw / gcc, получая файлы dll и .a
Я использую Code :: Blocks для этого, поэтому я поместил dll в рабочий каталог моего проекта, где находятся остальные dll, которые я использую, и решил запустить boost::python::exec("b = 5");
Мгновенно я получаю крах. Идеи?

#include <boost/python.hpp>

float func(int a)
{
return a*a-0.5;
}

BOOST_PYTHON_MODULE(test_module)
{
using namespace boost::python;
def("func", func);
}

int main()
{
//Try one
boost::python::exec("b = 5");
//Crash

//Try two
Py_Initialize();
boost::python::exec("b = 5");
//Works fine

//Try three
Py_Initialize();
boost::python::exec("import test_module");
//Throws boost::python::error_already_set and crashes

/*
Something along the lines of
boost::python::exec("import test_module\n""var = test_module.func( 3 )\n");
*/
}

В разделе параметров сборки моего проекта я добавил libboost_python3-mgw48-d-1_54.dll а также libpython33 быть связанным, так что это скомпилируется.
Идеи?

0

Решение

При встраивании Python почти все вызовы Python или Boost.Python должны выполняться после инициализации интерпретатора с помощью Py_Initialize(). Попытка вызвать интерпретатор перед инициализацией, например, с boost::python::exec(), приведет к неопределенному поведению.

В то время как это определяет источник сбоя, есть некоторые тонкие детали для достижения конечной цели встраивания Python и модуля, а затем exec импортировать встроенный модуль.

  • При импорте модуля Python сначала проверяет, является ли модуль встроенным модулем. Если модуль не является встроенным модулем, то Python попытается загрузить библиотеку на основе имени модуля и ожидает, что библиотека предоставит функцию, которая будет инициализировать модуль. Как test_module встраивается, его инициализация должна быть явно добавлена ​​так, чтобы import можно найти при поиске встроенных модулей.
  • import заявление использует __import__ функция. Эта функция должна быть доступна в execГлобалы.

Вот полный пример, демонстрирующий, как это сделать:

#include <boost/python.hpp>

float func(int a)
{
return a*a-0.5;
}

BOOST_PYTHON_MODULE(test_module)
{
using namespace boost::python;
def("func", func);
}

// Use macros to account for changes in Python 2 and 3:
// - Python's C API for embedding requires different naming conventions for
//   module initialization functions.
// - The builtins module was renamed.
#if PY_VERSION_HEX >= 0x03000000
#  define MODULE_INIT_FN(name) BOOST_PP_CAT(PyInit_, name)
#  define PYTHON_BUILTINS "builtins"#else
#  define MODULE_INIT_FN(name) BOOST_PP_CAT(init, name)
#  define PYTHON_BUILTINS "__builtin__"#endif

int main()
{
// Add the test_module module to the list of built-in modules.  This
// allows it to be imported with 'import test_module'.
PyImport_AppendInittab("test_module", &MODULE_INIT_FN(test_module));

Py_Initialize();

namespace python = boost::python;
try
{
// Create an empty dictionary that will function as a namespace.
python::dict ns;

// The 'import' statement depends on the __import__ function.  Thus,
// to enable 'import' to function the context of 'exec', the builtins
// module needs to be within the namespace being used.
ns["__builtins__"] = python::import(PYTHON_BUILTINS);

// Execute code.  Modifications to variables will be reflected in
// the ns.
python::exec("b = 5", ns);

std::cout << "b is " << python::extract<int>(ns["b"]) << std::endl;

// Execute code using the built-in test_module.
python::exec(
"import test_module\n""var = test_module.func(b)\n",
ns);

std::cout << "var is " << python::extract<float>(ns["var"]) << std::endl;
}
catch (python::error_already_set&)
{
PyErr_Print();
}
}

Когда выполнено, его вывод:

b is 5
var is 24.5
1

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

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

По вопросам рекламы [email protected]