summaryrefslogtreecommitdiffstats
path: root/src/boost/libs/python/example/quickstart/embedding.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/boost/libs/python/example/quickstart/embedding.cpp154
1 files changed, 154 insertions, 0 deletions
diff --git a/src/boost/libs/python/example/quickstart/embedding.cpp b/src/boost/libs/python/example/quickstart/embedding.cpp
new file mode 100644
index 000000000..65bcd16a0
--- /dev/null
+++ b/src/boost/libs/python/example/quickstart/embedding.cpp
@@ -0,0 +1,154 @@
+// Copyright Stefan Seefeld 2005.
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/python.hpp>
+
+#include <boost/detail/lightweight_test.hpp>
+#include <iostream>
+
+namespace python = boost::python;
+
+// An abstract base class
+class Base : public boost::noncopyable
+{
+public:
+ virtual ~Base() {};
+ virtual std::string hello() = 0;
+};
+
+// C++ derived class
+class CppDerived : public Base
+{
+public:
+ virtual ~CppDerived() {}
+ virtual std::string hello() { return "Hello from C++!";}
+};
+
+// Familiar Boost.Python wrapper class for Base
+struct BaseWrap : Base, python::wrapper<Base>
+{
+ virtual std::string hello()
+ {
+#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
+ // workaround for VC++ 6.x or 7.0, see
+ // http://boost.org/libs/python/doc/tutorial/doc/html/python/exposing.html#python.class_virtual_functions
+ return python::call<std::string>(this->get_override("hello").ptr());
+#else
+ return this->get_override("hello")();
+#endif
+ }
+};
+
+// Pack the Base class wrapper into a module
+BOOST_PYTHON_MODULE(embedded_hello)
+{
+ python::class_<BaseWrap, boost::noncopyable> base("Base");
+}
+
+
+void exec_test()
+{
+ std::cout << "registering extension module embedded_hello..." << std::endl;
+
+ // Register the module with the interpreter
+ if (PyImport_AppendInittab("embedded_hello", initembedded_hello) == -1)
+ throw std::runtime_error("Failed to add embedded_hello to the interpreter's "
+ "builtin modules");
+
+ std::cout << "defining Python class derived from Base..." << std::endl;
+
+ // Retrieve the main module
+ python::object main = python::import("__main__");
+
+ // Retrieve the main module's namespace
+ python::object global(main.attr("__dict__"));
+
+ // Define the derived class in Python.
+ python::object result = python::exec(
+ "from embedded_hello import * \n"
+ "class PythonDerived(Base): \n"
+ " def hello(self): \n"
+ " return 'Hello from Python!' \n",
+ global, global);
+
+ python::object PythonDerived = global["PythonDerived"];
+
+ // Creating and using instances of the C++ class is as easy as always.
+ CppDerived cpp;
+ BOOST_TEST(cpp.hello() == "Hello from C++!");
+
+ std::cout << "testing derived class from C++..." << std::endl;
+
+ // But now creating and using instances of the Python class is almost
+ // as easy!
+ python::object py_base = PythonDerived();
+ Base& py = python::extract<Base&>(py_base) BOOST_EXTRACT_WORKAROUND;
+
+ // Make sure the right 'hello' method is called.
+ BOOST_TEST(py.hello() == "Hello from Python!");
+
+ std::cout << "success!" << std::endl;
+}
+
+void exec_file_test(std::string const &script)
+{
+ std::cout << "running file " << script << "..." << std::endl;
+
+ // Run a python script in an empty environment.
+ python::dict global;
+ python::object result = python::exec_file(script.c_str(), global, global);
+
+ // Extract an object the script stored in the global dictionary.
+ BOOST_TEST(python::extract<int>(global["number"]) == 42);
+
+ std::cout << "success!" << std::endl;
+}
+
+void exec_test_error()
+{
+ std::cout << "intentionally causing a python exception..." << std::endl;
+
+ // Execute a statement that raises a python exception.
+ python::dict global;
+ python::object result = python::exec("print unknown \n", global, global);
+
+ std::cout << "Oops! This statement should be skipped due to an exception" << std::endl;
+}
+
+int main(int argc, char **argv)
+{
+ BOOST_TEST(argc == 2);
+ std::string script = argv[1];
+ // Initialize the interpreter
+ Py_Initialize();
+
+ bool error_expected = false;
+
+ if (
+ python::handle_exception(exec_test)
+ || python::handle_exception(boost::bind(exec_file_test, script))
+ || (
+ (error_expected = true)
+ && python::handle_exception(exec_test_error)
+ )
+
+ )
+ {
+ if (PyErr_Occurred())
+ {
+ if (!error_expected)
+ BOOST_ERROR("Python Error detected");
+ PyErr_Print();
+ }
+ else
+ {
+ BOOST_ERROR("A C++ exception was thrown for which "
+ "there was no exception translator registered.");
+ }
+ }
+
+ // Boost.Python doesn't support Py_Finalize yet, so don't call it!
+ return boost::report_errors();
+}