Advertisement
Guest User

Haoyu Bai

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