Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_34_1/libs/python/test/exec.cpp @ 29

Last change on this file since 29 was 29, checked in by landauf, 16 years ago

updated boost from 1_33_1 to 1_34_1

File size: 4.3 KB
Line 
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
12namespace python = boost::python;
13
14// An abstract base class
15class Base : public boost::noncopyable
16{
17public:
18  virtual ~Base() {};
19  virtual std::string hello() = 0;
20};
21
22// C++ derived class
23class CppDerived : public Base
24{
25public:
26  virtual ~CppDerived() {}
27  virtual std::string hello() { return "Hello from C++!";}
28};
29
30// Familiar Boost.Python wrapper class for Base
31struct 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
46BOOST_PYTHON_MODULE(embedded_hello)
47{
48  python::class_<BaseWrap, boost::noncopyable> base("Base");
49}
50
51
52void 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
59void exec_test()
60{
61  // Register the module with the interpreter
62  if (PyImport_AppendInittab("embedded_hello", initembedded_hello) == -1)
63    throw std::runtime_error("Failed to add embedded_hello to the interpreter's "
64                 "builtin modules");
65  // Retrieve the main module
66  python::object main = python::import("__main__");
67 
68  // Retrieve the main module's namespace
69  python::object global(main.attr("__dict__"));
70
71  // Define the derived class in Python.
72  python::object result = python::exec(
73    "from embedded_hello import *        \n"
74    "class PythonDerived(Base):          \n"
75    "    def hello(self):                \n"
76    "        return 'Hello from Python!' \n",
77    global, global);
78
79  python::object PythonDerived = global["PythonDerived"];
80
81  // Creating and using instances of the C++ class is as easy as always.
82  CppDerived cpp;
83  BOOST_TEST(cpp.hello() == "Hello from C++!");
84
85  // But now creating and using instances of the Python class is almost
86  // as easy!
87  python::object py_base = PythonDerived();
88  Base& py = python::extract<Base&>(py_base) BOOST_EXTRACT_WORKAROUND;
89
90  // Make sure the right 'hello' method is called.
91  BOOST_TEST(py.hello() == "Hello from Python!");
92}
93
94void exec_file_test(std::string const &script)
95{
96  // Run a python script in an empty environment.
97  python::dict global;
98  python::object result = python::exec_file(script.c_str(), global, global);
99
100  // Extract an object the script stored in the global dictionary.
101  BOOST_TEST(python::extract<int>(global["number"]) ==  42);
102}
103
104void exec_test_error()
105{
106  // Execute a statement that raises a python exception.
107  python::dict global;
108  python::object result = python::exec("print unknown \n", global, global);
109}
110
111int main(int argc, char **argv)
112{
113  BOOST_TEST(argc == 2);
114  std::string script = argv[1];
115  // Initialize the interpreter
116  Py_Initialize();
117
118  if (python::handle_exception(eval_test) ||
119      python::handle_exception(exec_test) ||
120      python::handle_exception(boost::bind(exec_file_test, script)))
121  {
122    if (PyErr_Occurred())
123    {
124      BOOST_ERROR("Python Error detected");
125      PyErr_Print();
126    }
127    else
128    {
129        BOOST_ERROR("A C++ exception was thrown  for which "
130                    "there was no exception handler registered.");
131    }
132  }
133 
134  if (python::handle_exception(exec_test_error))
135  {
136    if (PyErr_Occurred())
137    {
138      PyErr_Print();
139    }
140    else
141    {
142        BOOST_ERROR("A C++ exception was thrown  for which "
143                    "there was no exception handler registered.");
144    }
145  }
146  else
147  {
148      BOOST_ERROR("Python exception expected, but not seen.");
149  }
150 
151  // Boost.Python doesn't support Py_Finalize yet.
152  // Py_Finalize();
153  return boost::report_errors();
154}
155
156// Including this file makes sure
157// that on Windows, any crashes (e.g. null pointer dereferences) invoke
158// the debugger immediately, rather than being translated into structured
159// exceptions that can interfere with debugging.
160#include "module_tail.cpp"
Note: See TracBrowser for help on using the repository browser.