如何使用boost :: python创建和使用Python对象的实例

时间:2017-02-10 03:06:50

标签: c++ boost boost-python

假设我有一个类似的Python类:

class MyPythonClass:
    def Func1(self, param):
        return
    def Func2(self, strParam):
        return strParam

如果我想在我的C ++代码中嵌入包含该类的Python脚本,请通过我的C ++代码创建该对象的实例,然后调用该python对象上的成员,我该怎么做?

我认为会是这样的:

namespace python = boost::python;
python::object main = python::import("main");
python::object mainNamespace = main.attr("__dict__");
python::object script = python::exec_file(path_to_my_script, mainNamespace);
python::object foo = mainNamespace.attr("MyPythonClass")();
python::str func2return = foo.attr("Func2")("hola");
assert(func2return == "hola");

但是我尝试过的这段代码的许多变化并没有奏效。为了能够做到这一点,我需要为我的代码注入什么魔法酱?

2 个答案:

答案 0 :(得分:2)

这最终对我有用。

namespace python = boost::python;
python::object main = python::import("main");
python::object mainNamespace = main.attr("__dict__");

//add the contents of the script to the global namespace
python::object script = python::exec_file(path_to_my_script, mainNamespace);

//add an instance of the object to the global namespace
python::exec("foo = MyPythonClass()", mainNamespace);
//create boost::python::object that refers to the created object
python::object foo = main.attr("foo");

//call Func2 on the python::object via attr
//then extract the result into a const char* and assign it to a std::string
//the last bit could be done on multiple lines with more intermediate variables if desired
const std::string func2return = python::extract<const char*>(foo.attr("Func2")("hola"));
assert(func2return == "hola");

如果有更好的方法,请随意发表评论。

答案 1 :(得分:0)

下面是使用Boost :: python嵌入的示例。我特别喜欢这种方法,因为使用python类函数就像在python中一样容易。但是,这确实需要一些设置。

#include <boost/python.hpp>
// An abstract base class
class Base : public boost::noncopyable
{
public:
  virtual ~Base() {};
  virtual void func1() = 0;
  virtual std::string func2(std::string strParam) = 0;
}


// Boost.Python wrapper class for Base
// a function pointer to Base::hello and then calls function
struct BaseWrap : Base, python::wrapper<Base>
{

  virtual void func1()
  {
    this->get_override("func1")();
  }
  virtual void func2(std::string strParam)
  {
    std::string str = this->get_override("func2")(strParam);
    return str;
  }
}


// Pack the Base class wrapper into a module
BOOST_PYTHON_MODULE(embedded_py)
{
  //creating p c++ class instance called "base" and constructed with "Base"
  python::class_<BaseWrap, boost::noncopyable> base("Base");
}

int main()
{
  Py_Initialize();
  std::cout << "registering extension module embedded_py ..." << std::endl;

  // Register the module with the interpreter
  if (PyImport_AppendInittab("embedded_pi", initembedded_pi) == -1)
    throw std::runtime_error("Failed to add embedded_pi to the interpreter's "
                 "builtin modules");

  std::cout << "defining Python class derived from Base..." << std::endl;

  // Retrieve the main module
  python::object main = python::import("__main__");

  // Retrieve the main module's namespace
  python::object global(main.attr("__dict__"));

  // Load the python file
  std::string file = "YOUR_PYTHON_FILE.py";
  try{python::exec_file(file.c_str(),global,global);
  }catch(boost::python::error_already_set const &){
        // Parse and output the exception
        PyErr_Print();
        }

   // pull the python class from global
   // This is the name of MyPythonClass
   python::object LOT = global["LOT"];

   // Now creating and using instances of the Python class is almost easy
   python::object lot_base = LOT();
   Base& lot = python::extract<Base&>(lot_base) BOOST_EXTRACT_WORKAROUND;


  try{lot.func1();
  }catch(boost::python::error_already_set const &){
        PyErr_Print();
  }
  try{std::string hola = lot.func2("hello");
  }catch(boost::python::error_already_set const &){
        PyErr_Print();
  }

  Py_Finalize();

  return 1;
}