繁体   English   中英

通过Boost.Python嵌入,Python 3无法将C ++类识别为模块

[英]C++ class not recognized by Python 3 as a module via Boost.Python Embedding

Boost.Python v1.56中的以下示例显示了如何将Python 3.4.2解释器嵌入到您自己的应用程序中。 不幸的是,在Windows 8.1下使用MSVC2013进行配置时,该示例无法正常使用。 我还没有找到一个关于嵌入的完整示例,至少没有一个比10年左右更年轻。

运行它时收到以下错误: ImportError:'embedded_hello'不是内置模块

代码在这里: http//pastebin.com/shTtdxT8

任何暗示我可以做什么让这个运行? 一般来说如何在Python中公开c ++类,反之亦然?

代码正在使用Python 2头配置进行编译。 使用Python 3头配置进行编译时, boost/python/module_init.hpp会将embedded_hello模块的初始化函数声明为PyInit_embedded_hello而不是initembedded_hello 我强烈建议验证正确的头配置,并执行Boost.Python的干净构建,因为Boost.Python和使用库构建的模块需要使用相同的头配置。

此外,在将模块添加到内置表时, PyImport_AppendInittab()调用需要在Py_Initialize()之前Py_Initialize() PyImport_AppendInittab()文档明确指出:

将单个模块添加到现有内置模块表中。 ...这应该在Py_Initialize()之前Py_Initialize()

Boost.Python使用BOOST_PYTHON_MODULE宏来定义Python模块。 在模块的主体内,当前范围是模块本身。 因此,当通过类型包装器公开C ++类型时,例如当通过boost::python::class_将C ++类暴露给Python时,生成的Python类将位于BOOST_PYTHON_MODULE定义的模块中。

另一方面,在Python中声明的用户定义类型是第一类对象。 从C ++的角度来看,它们可以被视为工厂函数。 因此,要在C ++中使用Python定义的类,需要获取类对象的句柄,然后通过调用类对象来实例化类的实例。


这是一个完整的最小示例,演示了如何嵌入Python 3解释器:

  • 导入直接构建到二进制文件中的模块( example ),并将基本C ++类( spam_wrap )公开给具有默认的虚函数/调度的Python( example.Spam )。
  • 演示使用公开的Python类( example.Spam )。
  • 从Python( example.Spam )中公开的Python类( example.Spamexample.PySpam并使用生成的类。
#include <iostream>
#include <boost/python.hpp>

/// @brief Mockup Spam model.
struct spam
  : boost::noncopyable
{
  virtual ~spam() {};
  virtual std::string hello() { return "Hello from C++"; }
};

//@ brief Mockup Spam wrapper.
struct spam_wrap
  : spam,
    boost::python::wrapper<spam>
{
  virtual std::string hello()
  {
#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
    return boost::python::call<std::string>(
      this->get_override("hello").ptr());
#else
    return this->get_override("hello")();
#endif
  }

  std::string default_hello() { return this->spam::hello(); }
};

/// @brief Python example module.
BOOST_PYTHON_MODULE(example)
{
  namespace python = boost::python;

  // Expose C++ spam_wrap as Python Spam class.
  python::class_<spam_wrap, boost::noncopyable>("Spam")
    .def("hello", &spam::hello, &spam_wrap::default_hello)
    ;
}   

int main()
{
  // Add example to built-in.
  PyImport_AppendInittab("example", &PyInit_example);

  // Start the interpreter.
  Py_Initialize();

  namespace python = boost::python;
  try
  {
    python::object main = python::import("__main__");
    python::object global = main.attr("__dict__");

    // Execute Python code, using the example module.
    exec(
      "from example import Spam          \n"
      "spam = Spam()                     \n"
      "                                  \n"
      "class PySpam(Spam):               \n"
      "    def hello(self):              \n"
      "        return 'Hello from Python'\n",     
      global, global);

    /// Check the instance of the Python object using the C++ class.
    // >>> spam_object = spam
    python::object spam_object = global["spam"];
    assert(python::extract<spam>(spam_object).check());
    // >>> result = spam_object.hello()
    python::object result = spam_object.attr("hello")();
    // >>> print(result)
    std::cout << python::extract<std::string>(result)() << std::endl;
    // >>> assert("Hello from C++" == result)
    assert("Hello from C++" == python::extract<std::string>(result)());

    /// Create an instance using PySpam class.  It too is a Python object.
    // >>> py_spam_type = PySpam
    python::object py_spam_type = global["PySpam"];
    // >>> py_spam_object = py_spam_type()
    python::object py_spam_object = py_spam_type();
    // >>> result = py_spam_object()
    result = py_spam_object.attr("hello")();
    // >>> print(result)
    std::cout << python::extract<std::string>(result)() << std::endl;
    // >>> assert("Hello from Python" == result)
    assert("Hello from Python" == python::extract<std::string>(result)());
  }
  catch (const python::error_already_set&)
  {
    PyErr_Print();
  }
}

该程序应该运行完成而不会出现错误,从而产生以下输出:

Hello from C++
Hello from Python

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM