summaryrefslogtreecommitdiffstats
path: root/src/boost/libs/python/example/quickstart
diff options
context:
space:
mode:
Diffstat (limited to 'src/boost/libs/python/example/quickstart')
-rw-r--r--src/boost/libs/python/example/quickstart/Jamfile35
-rw-r--r--src/boost/libs/python/example/quickstart/embedding.cpp154
-rw-r--r--src/boost/libs/python/example/quickstart/extending.cpp41
-rw-r--r--src/boost/libs/python/example/quickstart/script.py7
-rw-r--r--src/boost/libs/python/example/quickstart/test_extending.py37
5 files changed, 274 insertions, 0 deletions
diff --git a/src/boost/libs/python/example/quickstart/Jamfile b/src/boost/libs/python/example/quickstart/Jamfile
new file mode 100644
index 000000000..6dd351301
--- /dev/null
+++ b/src/boost/libs/python/example/quickstart/Jamfile
@@ -0,0 +1,35 @@
+# Copyright Stefan Seefeld 2016.
+# 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)
+
+import python ;
+import testing ;
+
+project quickstart
+ : requirements
+ <location>.
+ ;
+
+# Declare a Python extension called hello.
+python-extension extending : extending.cpp ;
+
+# Declare an executable called embedding that embeds Python
+exe embedding : embedding.cpp /python//python ;
+
+# Declare a test of the extension module
+testing.make-test run-pyd : extending test_extending.py : : test_ext ;
+
+# Declare a test of the embedding application
+testing.run embedding embedding.cpp
+ : # any ordinary arguments
+ : script.py # any arguments that should be treated as relative paths
+ : # requirements
+ : test_embed ; # name of test
+
+# Create a "test" target that runs all the tests
+alias test : test_ext test_embed ;
+
+# make sure the tests don't run by default
+explicit test_ext test_embed test ;
+
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();
+}
diff --git a/src/boost/libs/python/example/quickstart/extending.cpp b/src/boost/libs/python/example/quickstart/extending.cpp
new file mode 100644
index 000000000..a539d3b4b
--- /dev/null
+++ b/src/boost/libs/python/example/quickstart/extending.cpp
@@ -0,0 +1,41 @@
+// Copyright Ralf W. Grosse-Kunstleve 2002-2004. 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/class.hpp>
+#include <boost/python/module.hpp>
+#include <boost/python/def.hpp>
+#include <iostream>
+#include <string>
+
+namespace { // Avoid cluttering the global namespace.
+
+ // A friendly class.
+ class hello
+ {
+ public:
+ hello(const std::string& country) { this->country = country; }
+ std::string greet() const { return "Hello from " + country; }
+ private:
+ std::string country;
+ };
+
+ // A function taking a hello object as an argument.
+ std::string invite(const hello& w) {
+ return w.greet() + "! Please come soon!";
+ }
+}
+
+BOOST_PYTHON_MODULE(extending)
+{
+ using namespace boost::python;
+ class_<hello>("hello", init<std::string>())
+ // Add a regular member function.
+ .def("greet", &hello::greet)
+ // Add invite() as a member of hello!
+ .def("invite", invite)
+ ;
+
+ // Also add invite() as a regular function to the module.
+ def("invite", invite);
+}
diff --git a/src/boost/libs/python/example/quickstart/script.py b/src/boost/libs/python/example/quickstart/script.py
new file mode 100644
index 000000000..c3e034ba8
--- /dev/null
+++ b/src/boost/libs/python/example/quickstart/script.py
@@ -0,0 +1,7 @@
+#! /usr/bin/env python
+# Copyright Stefan Seefeld 2006. 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)
+
+print('Hello World !')
+number = 42
diff --git a/src/boost/libs/python/example/quickstart/test_extending.py b/src/boost/libs/python/example/quickstart/test_extending.py
new file mode 100644
index 000000000..938c7b904
--- /dev/null
+++ b/src/boost/libs/python/example/quickstart/test_extending.py
@@ -0,0 +1,37 @@
+#! /usr/bin/env python
+# Copyright Ralf W. Grosse-Kunstleve 2006. 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)
+
+# Using the doctest module here to ensure that the results are as expected.
+r'''>>> from extending import *
+ >>> hi = hello('California')
+ >>> hi.greet()
+ 'Hello from California'
+ >>> invite(hi)
+ 'Hello from California! Please come soon!'
+ >>> hi.invite()
+ 'Hello from California! Please come soon!'
+
+ >>> class wordy(hello):
+ ... def greet(self):
+ ... return hello.greet(self) + ', where the weather is fine'
+ ...
+ >>> hi2 = wordy('Florida')
+ >>> hi2.greet()
+ 'Hello from Florida, where the weather is fine'
+ >>> invite(hi2)
+ 'Hello from Florida! Please come soon!'
+'''
+
+def run(args = None):
+ if args is not None:
+ import sys
+ sys.argv = args
+ import doctest, test_extending
+ return doctest.testmod(test_extending, verbose=True)
+
+if __name__ == '__main__':
+ import sys
+ sys.exit(run()[0])
+