Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_34_1/libs/python/example/quickstart/embedding.cpp @ 29

Last change on this file since 29 was 29, checked in by landauf, 17 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
11namespace python = boost::python;
12
13// An abstract base class
14class Base : public boost::noncopyable
15{
16public:
17  virtual ~Base() {};
18  virtual std::string hello() = 0;
19};
20
21// C++ derived class
22class CppDerived : public Base
23{
24public:
25  virtual ~CppDerived() {}
26  virtual std::string hello() { return "Hello from C++!";}
27};
28
29// Familiar Boost.Python wrapper class for Base
30struct BaseWrap : Base, python::wrapper<Base>
31{
32  virtual std::string hello() 
33  {
34#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
35    // workaround for VC++ 6.x or 7.0, see
36    // http://boost.org/libs/python/doc/tutorial/doc/html/python/exposing.html#python.class_virtual_functions
37    return python::call<std::string>(this->get_override("hello").ptr());
38#else
39    return this->get_override("hello")();
40#endif
41  }
42};
43
44// Pack the Base class wrapper into a module
45BOOST_PYTHON_MODULE(embedded_hello)
46{
47  python::class_<BaseWrap, boost::noncopyable> base("Base");
48}
49
50
51void exec_test()
52{
53    std::cout << "registering extension module embedded_hello..." << std::endl;
54   
55  // Register the module with the interpreter
56  if (PyImport_AppendInittab("embedded_hello", initembedded_hello) == -1)
57    throw std::runtime_error("Failed to add embedded_hello to the interpreter's "
58                 "builtin modules");
59
60  std::cout << "defining Python class derived from Base..." << std::endl;
61 
62  // Retrieve the main module
63  python::object main = python::import("__main__");
64 
65  // Retrieve the main module's namespace
66  python::object global(main.attr("__dict__"));
67
68  // Define the derived class in Python.
69  python::object result = python::exec(
70    "from embedded_hello import *        \n"
71    "class PythonDerived(Base):          \n"
72    "    def hello(self):                \n"
73    "        return 'Hello from Python!' \n",
74    global, global);
75
76  python::object PythonDerived = global["PythonDerived"];
77
78  // Creating and using instances of the C++ class is as easy as always.
79  CppDerived cpp;
80  BOOST_TEST(cpp.hello() == "Hello from C++!");
81
82  std::cout << "testing derived class from C++..." << std::endl;
83 
84  // But now creating and using instances of the Python class is almost
85  // as easy!
86  python::object py_base = PythonDerived();
87  Base& py = python::extract<Base&>(py_base) BOOST_EXTRACT_WORKAROUND;
88
89  // Make sure the right 'hello' method is called.
90  BOOST_TEST(py.hello() == "Hello from Python!");
91
92  std::cout << "success!" << std::endl;
93}
94
95void exec_file_test(std::string const &script)
96{
97    std::cout << "running file " << script << "..." << std::endl;
98   
99    // Run a python script in an empty environment.
100    python::dict global;
101    python::object result = python::exec_file(script.c_str(), global, global);
102
103    // Extract an object the script stored in the global dictionary.
104    BOOST_TEST(python::extract<int>(global["number"]) ==  42);
105   
106    std::cout << "success!" << std::endl;
107}
108
109void exec_test_error()
110{
111    std::cout << "intentionally causing a python exception..." << std::endl;
112   
113    // Execute a statement that raises a python exception.
114    python::dict global;
115    python::object result = python::exec("print unknown \n", global, global);
116
117    std::cout << "Oops! This statement should be skipped due to an exception" << std::endl;
118}
119
120int main(int argc, char **argv)
121{
122  BOOST_TEST(argc == 2);
123  std::string script = argv[1];
124  // Initialize the interpreter
125  Py_Initialize();
126
127  bool error_expected = false;
128 
129  if (
130      python::handle_exception(exec_test)
131      || python::handle_exception(boost::bind(exec_file_test, script))
132      || (
133          (error_expected = true)
134          && python::handle_exception(exec_test_error)
135      )
136
137  )
138  {
139    if (PyErr_Occurred())
140    {
141        if (!error_expected)
142            BOOST_ERROR("Python Error detected");
143        PyErr_Print();
144    }
145    else
146    {
147        BOOST_ERROR("A C++ exception was thrown  for which "
148                    "there was no exception translator registered.");
149    }
150  }
151 
152  // Boost.Python doesn't support Py_Finalize yet, so don't call it!
153  return boost::report_errors();
154}
Note: See TracBrowser for help on using the repository browser.