Haoyu Bai - Pastebin.com (original) (raw)

  1. // Copyright Stefan Seefeld 2005.
  2. // Distributed under the Boost Software License, Version 1.0. (See
  3. // accompanying file LICENSE_1_0.txt or copy at
  4. // http://www.boost.org/LICENSE\_1\_0.txt)
  5. #include <boost/python.hpp>
  6. #include <boost/detail/lightweight_test.hpp>
  7. #include
  8. namespace python = boost::python;
  9. // An abstract base class
  10. class Base : public boost::noncopyable
  11. {
  12. public:
  13. virtual ~Base() {};
  14. virtual std::string hello() = 0;
  15. };
  16. // C++ derived class
  17. class CppDerived : public Base
  18. {
  19. public:
  20. virtual ~CppDerived() {}
  21. virtual std::string hello() { return "Hello from C++!";}
  22. };
  23. // Familiar Boost.Python wrapper class for Base
  24. struct BaseWrap : Base, python::wrapper<Base>
  25. {
  26. virtual std::string hello()
  27. {
  28. #if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
  29. // workaround for VC++ 6.x or 7.0, see
  30. // http://boost.org/libs/python/doc/tutorial/doc/html/python/exposing.html#python.class\_virtual\_functions
  31. return python::callstd::string\(this->get_override("hello").ptr());
  32. #else
  33. return this->get_override("hello")();
  34. #endif
  35. }
  36. };
  37. // Pack the Base class wrapper into a module
  38. BOOST_PYTHON_MODULE(embedded_hello)
  39. {
  40. python::class_<BaseWrap, boost::noncopyable> base("Base");
  41. }
  42. void eval_test()
  43. {
  44. python::object result = python::eval("'abcdefg'.upper()");
  45. std::string value = python::extractstd::string\(result) BOOST_EXTRACT_WORKAROUND;
  46. BOOST_TEST(value == "ABCDEFG");
  47. }
  48. void exec_test()
  49. {
  50. // Register the module with the interpreter
  51. if (PyImport_AppendInittab(const_cast<char*>("embedded_hello"),
  52. #if PY_VERSION_HEX >= 0x03000000
  53. PyInit_embedded_hello
  54. #else
  55. initembedded_hello
  56. #endif
  57. ) == -1)
  58. throw std::runtime_error("Failed to add embedded_hello to the interpreter's "
  59. "builtin modules");
  60. // Retrieve the main module
  61. python::object main = python::import("__main__");
  62. // Retrieve the main module's namespace
  63. python::object global(main.attr("__dict__"));
  64. // Define the derived class in Python.
  65. python::object result = python::exec(
  66. "from embedded_hello import * \n"
  67. "class PythonDerived(Base): \n"
  68. " def hello(self): \n"
  69. " return 'Hello from Python!' \n",
  70. global, global);
  71. python::object PythonDerived = global["PythonDerived"];
  72. // Creating and using instances of the C++ class is as easy as always.
  73. CppDerived cpp;
  74. BOOST_TEST(cpp.hello() == "Hello from C++!");
  75. // But now creating and using instances of the Python class is almost
  76. // as easy!
  77. python::object py_base = PythonDerived();
  78. Base& py = python::extract<Base&>(py_base) BOOST_EXTRACT_WORKAROUND;
  79. // Make sure the right 'hello' method is called.
  80. BOOST_TEST(py.hello() == "Hello from Python!");
  81. }
  82. void exec_file_test(std::string const &script)
  83. {
  84. // Run a python script in an empty environment.
  85. python::dict global;
  86. python::object result = python::exec_file(script.c_str(), global, global);
  87. // Extract an object the script stored in the global dictionary.
  88. BOOST_TEST(python::extract<int>(global["number"]) == 42);
  89. }
  90. void exec_test_error()
  91. {
  92. // Execute a statement that raises a python exception.
  93. python::dict global;
  94. python::object result = python::exec("print(unknown) \n", global, global);
  95. }
  96. int main(int argc, char **argv)
  97. {
  98. BOOST_TEST(argc == 2);
  99. std::string script = argv[1];
  100. for(int i=0; i<10; ++i) {
  101. // Initialize the interpreter
  102. Py_Initialize();
  103. if (python::handle_exception(eval_test)
  104. || python::handle_exception(exec_test)
  105. || python::handle_exception(boost::bind(exec_file_test, script))
  106. )
  107. {
  108. if (PyErr_Occurred())
  109. {
  110. BOOST_ERROR("Python Error detected");
  111. PyErr_Print();
  112. }
  113. else
  114. {
  115. BOOST_ERROR("A C++ exception was thrown for which "
  116. "there was no exception handler registered.");
  117. }
  118. }
  119. std::cout << "try to write something..." << std::endl;
  120. Py_Finalize();
  121. Py_Initialize();
  122. if (python::handle_exception(exec_test_error))
  123. {
  124. if (PyErr_Occurred())
  125. {
  126. PyErr_Print();
  127. }
  128. else
  129. {
  130. BOOST_ERROR("A C++ exception was thrown for which "
  131. "there was no exception handler registered.");
  132. }
  133. }
  134. else
  135. {
  136. BOOST_ERROR("Python exception expected, but not seen.");
  137. }
  138. // Boost.Python doesn't support Py_Finalize yet.
  139. Py_Finalize();
  140. }
  141. return boost::report_errors();
  142. }
  143. // Including this file makes sure
  144. // that on Windows, any crashes (e.g. null pointer dereferences) invoke
  145. // the debugger immediately, rather than being translated into structured
  146. // exceptions that can interfere with debugging.
  147. #include "module_tail.cpp"