簡體   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