Stefano Mtangoo
Stefano Mtangoo

Reputation: 6550

Python/C++ Interoperabilty

I want to extend my C++ application to include Python interpreter. After good time in research, boost.python seems to be what I want. But somehow I cannot get it to work. Basically I want to load and execute Python scripts with my C++ app. I will be passing instance of PyEditor class which scripts can then call variety of methods. I use callback mechanisms to inform scripts of changes.

Now I cannot compile my code. It keep telling me

libs/boost-1.5.8/boost/python/module_init.hpp:79:8: error: expected unqualified-id before string constant
extern "C" __attribute__ ((__visibility__("default"))) _BOOST_PYTHON_MODULE_INIT(name)
libs/boost-1.5.8/boost/python/module.hpp:11:30: note: in expansion of macro ‘BOOST_PYTHON_MODULE_INIT’
# define BOOST_PYTHON_MODULE BOOST_PYTHON_MODULE_INIT

here is my function for loading scripts

void PythonManager::LoadModules()
{

    BOOST_PYTHON_MODULE(PyManager)
    {
        boost::python::class_<PyEditor>("PyEditor", boost::python::no_init)
        .def("GetText",&PyEditor::GetText)
        .def("GetText",&PyEditor::SetText)
        .def("AddCallable",&PyEditor::AddCallable);
    }
    PyImport_AppendInittab("PyManager");

    Py_Initialize();

    boost::python::object pyManagerModule((handle<>(PyImport_ImportModule("PyManager"))));
    main_namespace["PyManager"] = pyManagerModule;
    scope(cpp_module).attr("editor") = boost::python::ptr(new PyEditor());

    //Load the .py files 
}

I have read almost every resource I could yet I cannot understand my error

Upvotes: 1

Views: 323

Answers (1)

Tanner Sansbury
Tanner Sansbury

Reputation: 51871

The BOOST_PYTHON_MODULE macro is syntax sugar for declaring a Python module initialization function. The compiler is complaining about an attempt define a nested named function. Moving the BOOST_PYTHON_MODULE block to a scope where defining named functions is allowed, such as the global namespace, should resolve the problem:

BOOST_PYTHON_MODULE(PyManager)
{
  ...
}

void PythonManager::LoadModules()
{
  PyImport_AppendInittab("PyManager", &initPyManager);
  ...
}

Here is a complete example demonstrating importing a statically linked Python module when embedding:

#include <boost/python.hpp>

BOOST_PYTHON_MODULE(example)
{
  boost::python::def("calc", +[](int x) { return x * 2; });
}

int main()
{
  namespace python = boost::python;
  try
  {
    PyImport_AppendInittab("example", &initexample);

    Py_Initialize(); // Start interpreter.

    // Create the __main__ module.
    python::object main = python::import("__main__");
    python::object main_namespace = main.attr("__dict__");

    // >>> import example
    main_namespace["example"] = python::import("example");
    // >>> assert(42 == example.calc(21))
    python::object result = main_namespace["example"].attr("calc")(21);
    assert(42 == python::extract<int>(result)());
  }
  catch (const python::error_already_set&)
  {
    PyErr_Print();
  }
}

The above program runs to completion without error and has the equivalent Python code annotated within the comments.

Upvotes: 1

Related Questions