Initial commit
diff --git a/example/example.cpp b/example/example.cpp
new file mode 100644
index 0000000..800fb9f
--- /dev/null
+++ b/example/example.cpp
@@ -0,0 +1,36 @@
+/*
+    example/example.cpp -- pybind example plugin
+
+    Copyright (c) 2015 Wenzel Jakob <wenzel@inf.ethz.ch>
+
+    All rights reserved. Use of this source code is governed by a
+    BSD-style license that can be found in the LICENSE file.
+*/
+
+#include "example.h"
+
+void init_ex1(py::module &);
+void init_ex2(py::module &);
+void init_ex3(py::module &);
+void init_ex4(py::module &);
+void init_ex5(py::module &);
+void init_ex6(py::module &);
+void init_ex7(py::module &);
+void init_ex8(py::module &);
+void init_ex9(py::module &);
+
+PYTHON_PLUGIN(example) {
+    py::module m("example", "pybind example plugin");
+
+    init_ex1(m);
+    init_ex2(m);
+    init_ex3(m);
+    init_ex4(m);
+    init_ex5(m);
+    init_ex6(m);
+    init_ex7(m);
+    init_ex8(m);
+    init_ex9(m);
+
+    return m.ptr();
+}
diff --git a/example/example.h b/example/example.h
new file mode 100644
index 0000000..67434bb
--- /dev/null
+++ b/example/example.h
@@ -0,0 +1,7 @@
+#include <pybind/pybind.h>
+#include <iostream>
+
+using std::cout;
+using std::endl;
+
+namespace py = pybind;
diff --git a/example/example1.cpp b/example/example1.cpp
new file mode 100644
index 0000000..0cdc1f0
--- /dev/null
+++ b/example/example1.cpp
@@ -0,0 +1,92 @@
+/*
+    example/example1.cpp -- Example 1: constructors, deconstructors,
+    attribute access, __str__, argument and return value conventions
+
+    Copyright (c) 2015 Wenzel Jakob <wenzel@inf.ethz.ch>
+
+    All rights reserved. Use of this source code is governed by a
+    BSD-style license that can be found in the LICENSE file.
+*/
+
+#include "example.h"
+
+class Example1 {
+public:
+    Example1() {
+        cout << "Called Example1 default constructor.." << endl;
+    }
+    Example1(int value) : value(value) {
+        cout << "Called Example1 constructor with value " << value << ".." << endl;
+    }
+    Example1(const Example1 &e) : value(e.value) {
+        cout << "Called Example1 copy constructor with value " << value << ".." << endl;
+    }
+    Example1(Example1 &&e) : value(e.value) {
+        cout << "Called Example1 move constructor with value " << value << ".." << endl;
+        e.value = 0;
+    }
+    ~Example1() {
+        cout << "Called Example1 destructor (" << value << ")" << endl;
+    }
+    std::string toString() {
+        return "Example1[value=" + std::to_string(value) + "]";
+    }
+
+    void operator=(const Example1 &e) { cout << "Assignment operator" << endl; value = e.value; }
+    void operator=(Example1 &&e) { cout << "Move assignment operator" << endl; value = e.value; e.value = 0;}
+
+    void add1(Example1 other) { value += other.value; }           // passing py value
+    void add2(Example1 &other) { value += other.value; }          // passing by reference
+    void add3(const Example1 &other) { value += other.value; }    // passing by const reference
+    void add4(Example1 *other) { value += other->value; }         // passing py pointer
+    void add5(const Example1 *other) { value += other->value; }   // passing by const pointer
+
+    void add6(int other) { value += other; }                      // passing py value
+    void add7(int &other) { value += other; }                     // passing by reference
+    void add8(const int &other) { value += other; }               // passing by const reference
+    void add9(int *other) { value += *other; }                    // passing py pointer
+    void add10(const int *other) { value += *other; }             // passing by const pointer
+
+    Example1 self1() { return *this; }                            // return by value
+    Example1 &self2() { return *this; }                           // return by reference
+    const Example1 &self3() { return *this; }                     // return by const reference
+    Example1 *self4() { return this; }                            // return by pointer
+    const Example1 *self5() { return this; }                      // return by const pointer
+
+    int internal1() { return value; }                             // return by value
+    int &internal2() { return value; }                            // return by reference
+    const int &internal3() { return value; }                      // return by const reference
+    int *internal4() { return &value; }                           // return by pointer
+    const int *internal5() { return &value; }                     // return by const pointer
+
+    int value = 0;
+};
+
+void init_ex1(py::module &m) {
+    py::class_<Example1>(m, "Example1")
+        .def(py::init<>())
+        .def(py::init<int>())
+        .def(py::init<const Example1&>())
+        .def("add1", &Example1::add1)
+        .def("add2", &Example1::add2)
+        .def("add3", &Example1::add3)
+        .def("add4", &Example1::add4)
+        .def("add5", &Example1::add5)
+        .def("add6", &Example1::add6)
+        .def("add7", &Example1::add7)
+        .def("add8", &Example1::add8)
+        .def("add9", &Example1::add9)
+        .def("add10", &Example1::add10)
+        .def("self1", &Example1::self1)
+        .def("self2", &Example1::self2)
+        .def("self3", &Example1::self3)
+        .def("self4", &Example1::self4)
+        .def("self5", &Example1::self5)
+        .def("internal1", &Example1::internal1)
+        .def("internal2", &Example1::internal2)
+        .def("internal3", &Example1::internal3)
+        .def("internal4", &Example1::internal4)
+        .def("internal5", &Example1::internal5)
+        .def("__str__", &Example1::toString)
+        .def_readwrite("value", &Example1::value);
+}
diff --git a/example/example1.py b/example/example1.py
new file mode 100755
index 0000000..30cda8d
--- /dev/null
+++ b/example/example1.py
@@ -0,0 +1,36 @@
+#!/usr/bin/env python3
+import sys
+sys.path.append('.')
+
+from example import Example1
+
+instance1 = Example1()
+instance2 = Example1(32)
+instance1.add1(instance2)
+instance1.add2(instance2)
+instance1.add3(instance2)
+instance1.add4(instance2)
+instance1.add5(instance2)
+instance1.add6(32)
+instance1.add7(32)
+instance1.add8(32)
+instance1.add9(32)
+instance1.add10(32)
+
+print("Instance 1: " + str(instance1))
+print("Instance 2: " + str(instance2))
+
+print(instance1.self1())
+print(instance1.self2())
+print(instance1.self3())
+print(instance1.self4())
+print(instance1.self5())
+print(instance1.internal1())
+print(instance1.internal2())
+print(instance1.internal3())
+print(instance1.internal4())
+print(instance1.internal5())
+
+print("Instance 1, direct access = %i" % instance1.value)
+instance1.value = 100
+print("Instance 1: " + str(instance1))
diff --git a/example/example1.ref b/example/example1.ref
new file mode 100644
index 0000000..deeb40c
--- /dev/null
+++ b/example/example1.ref
@@ -0,0 +1,28 @@
+Called Example1 default constructor..
+Called Example1 constructor with value 32..
+Called Example1 copy constructor with value 32..
+Called Example1 move constructor with value 32..
+Called Example1 move constructor with value 32..
+Called Example1 destructor (32)
+Called Example1 destructor (0)
+Called Example1 destructor (0)
+Called Example1 copy constructor with value 320..
+Called Example1 copy constructor with value 320..
+Called Example1 destructor (320)
+Called Example1 destructor (320)
+Instance 1: Example1[value=320]
+Instance 2: Example1[value=32]
+Example1[value=320]
+Example1[value=320]
+Example1[value=320]
+Example1[value=320]
+Example1[value=320]
+320
+320
+320
+320
+320
+Instance 1, direct access = 320
+Instance 1: Example1[value=100]
+Called Example1 destructor (32)
+Called Example1 destructor (100)
diff --git a/example/example2.cpp b/example/example2.cpp
new file mode 100644
index 0000000..d064fb3
--- /dev/null
+++ b/example/example2.cpp
@@ -0,0 +1,117 @@
+/*
+    example/example2.cpp2 -- Example 2: singleton design pattern, static
+    functions and variables, passing and interacting with Python types
+
+    Copyright (c) 2015 Wenzel Jakob <wenzel@inf.ethz.ch>
+
+    All rights reserved. Use of this source code is governed by a
+    BSD-style license that can be found in the LICENSE file.
+*/
+
+#include "example.h"
+
+class Example2 {
+public:
+    static Example2 *new_instance() {
+        return new Example2();
+    }
+    ~Example2() {
+        std::cout << "Destructing Example2" << std::endl;
+    }
+
+    /* Create and return a Python dictionary */
+    py::dict get_dict() {
+        py::dict dict;
+        dict[py::str("key")] = py::str("value");
+        return dict;
+    }
+
+    /* Create and return a C++ dictionary */
+    std::map<std::string, std::string> get_dict_2() {
+        std::map<std::string, std::string> result;
+        result["key"] = "value";
+        return result;
+    }
+
+    /* Create, manipulate, and return a Python list */
+    py::list get_list() {
+        py::list list;
+        list.append(py::str("value"));
+        cout << "Entry at positon 0: " << py::object(list[0]) << endl;
+        list[0] = py::str("overwritten");
+        return list;
+    }
+
+    /* C++ STL data types are automatically casted */
+    std::vector<std::string> get_list_2() {
+        std::vector<std::string> list;
+        list.push_back("value");
+        return list;
+    }
+
+    /* Easily iterate over a dictionary using a C++11 range-based for loop */
+    void print_dict(py::dict dict) {
+        for (auto item : dict)
+            std::cout << "key: " << item.first << ", value=" << item.second << std::endl;
+    }
+
+    /* STL data types are automatically casted from Python */
+    void print_dict_2(const std::map<std::string, std::string> &dict) {
+        for (auto item : dict)
+            std::cout << "key: " << item.first << ", value=" << item.second << std::endl;
+    }
+
+    /* Easily iterate over a list using a C++11 range-based for loop */
+    void print_list(py::list list) {
+        int index = 0;
+        for (auto item : list)
+            std::cout << "list item " << index++ << ": " << item << std::endl;
+    }
+
+    /* STL data types are automatically casted from Python */
+    void print_list_2(std::vector<std::string> &list) {
+        int index = 0;
+        for (auto item : list)
+            std::cout << "list item " << index++ << ": " << item << std::endl;
+    }
+
+    /* pybind automatically translates between C++11 and Python tuples */
+    std::pair<std::string, bool> pair_passthrough(std::pair<bool, std::string> input) {
+        return std::make_pair(input.second, input.first);
+    }
+
+    /* pybind automatically translates between C++11 and Python tuples */
+    std::tuple<int, std::string, bool> tuple_passthrough(std::tuple<bool, std::string, int> input) {
+        return std::make_tuple(std::get<2>(input), std::get<1>(input), std::get<0>(input));
+    }
+
+    void throw_exception() {
+        throw std::runtime_error("This exception was intentionally thrown.");
+    }
+
+    static int value;
+    static const int value2;
+};
+
+int Example2::value = 0;
+const int Example2::value2 = 5;
+
+void init_ex2(py::module &m) {
+    /* No constructor is explicitly defined below. An exception is raised when
+       trying to construct it directly from Python */
+    py::class_<Example2>(m, "Example2")
+        .def("get_dict", &Example2::get_dict, "Return a Python dictionary")
+        .def("get_dict_2", &Example2::get_dict_2, "Return a C++ dictionary")
+        .def("get_list", &Example2::get_list, "Return a Python list")
+        .def("get_list_2", &Example2::get_list_2, "Return a C++ list")
+        .def("print_dict", &Example2::print_dict, "Print entries of a Python dictionary")
+        .def("print_dict_2", &Example2::print_dict_2, "Print entries of a C++ dictionary")
+        .def("print_list", &Example2::print_list, "Print entries of a Python list")
+        .def("print_list_2", &Example2::print_list_2, "Print entries of a C++ list")
+        .def("pair_passthrough", &Example2::pair_passthrough, "Return a pair in reversed order")
+        .def("tuple_passthrough", &Example2::tuple_passthrough, "Return a triple in reversed order")
+        .def("throw_exception", &Example2::throw_exception, "Throw an exception")
+        .def_static("new_instance", &Example2::new_instance, "Return an instance")
+        .def_readwrite_static("value", &Example2::value, "Static value member")
+        .def_readonly_static("value2", &Example2::value2, "Static value member (readonly)");
+}
diff --git a/example/example2.py b/example/example2.py
new file mode 100755
index 0000000..b0f4707
--- /dev/null
+++ b/example/example2.py
@@ -0,0 +1,47 @@
+#!/usr/bin/env python3
+import sys, pydoc
+sys.path.append('.')
+
+from example import Example2
+
+Example2.value = 15
+print(Example2.value)
+print(Example2.value2)
+
+try:
+    Example2()
+except Exception as e:
+    print(e)
+
+try:
+    Example2.value2 = 15
+except Exception as e:
+    print(e)
+
+instance = Example2.new_instance()
+
+dict_result = instance.get_dict()
+dict_result['key2'] = 'value2'
+instance.print_dict(dict_result)
+
+dict_result = instance.get_dict_2()
+dict_result['key2'] = 'value2'
+instance.print_dict_2(dict_result)
+
+list_result = instance.get_list()
+list_result.append('value2')
+instance.print_list(list_result)
+
+list_result = instance.get_list_2()
+list_result.append('value2')
+instance.print_list_2(list_result)
+
+try:
+    instance.throw_exception()
+except Exception as e:
+    print(e)
+
+print(instance.pair_passthrough((True, "test")))
+print(instance.tuple_passthrough((True, "test", 5)))
+
+print(pydoc.render_doc(Example2, "Help on %s"))
diff --git a/example/example2.ref b/example/example2.ref
new file mode 100644
index 0000000..8367f20
--- /dev/null
+++ b/example/example2.ref
@@ -0,0 +1,91 @@
+key: key, value=value
+key: key2, value=value2
+key: key, value=value
+key: key2, value=value2
+Entry at positon 0: value
+list item 0: overwritten
+list item 1: value2
+list item 0: value
+list item 1: value2
+15
+5
+example.Example2: No constructor defined!
+can't set attribute
+This exception was intentionally thrown.
+('test', True)
+(5, 'test', True)
+Help on class Example2 in module example
+
+class EExxaammppllee22(builtins.object)
+ |  Methods defined here:
+ |  
+ |  ____iinniitt____(self, /, *args, **kwargs)
+ |      Initialize self.  See help(type(self)) for accurate signature.
+ |  
+ |  ____nneeww____ = <built-in method __new__ of example.Example2_meta object>
+ |  ggeett__ddiicctt(...) from builtins.PyCapsule
+ |      Signature : get_dict(Example2) -> dict
+ |      
+ |      Return a Python dictionary
+ |  
+ |  ggeett__ddiicctt__22(...) from builtins.PyCapsule
+ |      Signature : get_dict_2(Example2) -> dict<str, str>
+ |      
+ |      Return a C++ dictionary
+ |  
+ |  ggeett__lliisstt(...) from builtins.PyCapsule
+ |      Signature : get_list(Example2) -> list
+ |      
+ |      Return a Python list
+ |  
+ |  ggeett__lliisstt__22(...) from builtins.PyCapsule
+ |      Signature : get_list_2(Example2) -> list<str>
+ |      
+ |      Return a C++ list
+ |  
+ |  nneeww__iinnssttaannccee(...) from builtins.PyCapsule
+ |      Signature : new_instance() -> Example2
+ |      
+ |      Return an instance
+ |  
+ |  ppaaiirr__ppaasssstthhrroouugghh(...) from builtins.PyCapsule
+ |      Signature : pair_passthrough(Example2, (bool, str)) -> (str, bool)
+ |      
+ |      Return a pair in reversed order
+ |  
+ |  pprriinntt__ddiicctt(...) from builtins.PyCapsule
+ |      Signature : print_dict(Example2, dict) -> None
+ |      
+ |      Print entries of a Python dictionary
+ |  
+ |  pprriinntt__ddiicctt__22(...) from builtins.PyCapsule
+ |      Signature : print_dict_2(Example2, dict<str, str>) -> None
+ |      
+ |      Print entries of a C++ dictionary
+ |  
+ |  pprriinntt__lliisstt(...) from builtins.PyCapsule
+ |      Signature : print_list(Example2, list) -> None
+ |      
+ |      Print entries of a Python list
+ |  
+ |  pprriinntt__lliisstt__22(...) from builtins.PyCapsule
+ |      Signature : print_list_2(Example2, list<str>) -> None
+ |      
+ |      Print entries of a C++ list
+ |  
+ |  tthhrrooww__eexxcceeppttiioonn(...) from builtins.PyCapsule
+ |      Signature : throw_exception(Example2) -> None
+ |      
+ |      Throw an exception
+ |  
+ |  ttuuppllee__ppaasssstthhrroouugghh(...) from builtins.PyCapsule
+ |      Signature : tuple_passthrough(Example2, (bool, str, int32_t)) -> (int32_t, str, bool)
+ |      
+ |      Return a triple in reversed order
+ |  
+ |  ----------------------------------------------------------------------
+ |  Data and other attributes defined here:
+ |  
+ |  ____iinnssttaannccee__ssiizzee____ = 1
+
+Destructing Example2
diff --git a/example/example3.cpp b/example/example3.cpp
new file mode 100644
index 0000000..fec5d30
--- /dev/null
+++ b/example/example3.cpp
@@ -0,0 +1,65 @@
+/*
+    example/example3.cpp -- Example 3: operator overloading
+
+    Copyright (c) 2015 Wenzel Jakob <wenzel@inf.ethz.ch>
+
+    All rights reserved. Use of this source code is governed by a
+    BSD-style license that can be found in the LICENSE file.
+*/
+
+#include "example.h"
+#include <pybind/operators.h>
+
+class Vector2 {
+public:
+    Vector2(float x, float y) : x(x), y(y) { std::cout << "Value constructor" << std::endl; }
+    Vector2(const Vector2 &v) : x(v.x), y(v.y) { std::cout << "Copy constructor" << std::endl; }
+    Vector2(Vector2 &&v) : x(v.x), y(v.y) { std::cout << "Move constructor" << std::endl; v.x = v.y = 0; }
+    ~Vector2() { std::cout << "Destructor." << std::endl; }
+
+    std::string toString() const {
+        return "[" + std::to_string(x) + ", " + std::to_string(y) + "]";
+    }
+
+    void operator=(const Vector2 &v) {
+        cout << "Assignment operator" << endl;
+        x = v.x;
+        y = v.y;
+    }
+
+    void operator=(Vector2 &&v) {
+        cout << "Move assignment operator" << endl;
+        x = v.x; y = v.y; v.x = v.y = 0;
+    }
+
+    Vector2 operator+(const Vector2 &v) const { return Vector2(x + v.x, y + v.y); }
+    Vector2 operator-(const Vector2 &v) const { return Vector2(x - v.x, y - v.y); }
+    Vector2 operator-(float value) const { return Vector2(x - value, y - value); }
+    Vector2 operator+(float value) const { return Vector2(x + value, y + value); }
+    Vector2 operator*(float value) const { return Vector2(x * value, y * value); }
+    Vector2 operator/(float value) const { return Vector2(x / value, y / value); }
+    Vector2& operator+=(const Vector2 &v) { x += v.x; y += v.y; return *this; }
+    Vector2& operator-=(const Vector2 &v) { x -= v.x; y -= v.y; return *this; }
+    Vector2& operator*=(float v) { x *= v; y *= v; return *this; }
+    Vector2& operator/=(float v) { x /= v; y /= v; return *this; }
+private:
+    float x, y;
+};
+
+void init_ex3(py::module &m) {
+    py::class_<Vector2>(m, "Vector2")
+        .def(py::init<float, float>())
+        .def(py::self + py::self)
+        .def(py::self + float())
+        .def(py::self - py::self)
+        .def(py::self - float())
+        .def(py::self * float())
+        .def(py::self / float())
+        .def(py::self += py::self)
+        .def(py::self -= py::self)
+        .def(py::self *= float())
+        .def(py::self /= float())
+        .def("__str__", &Vector2::toString);
+
+    m.attr("Vector") = m.attr("Vector2");
+}
diff --git a/example/example3.py b/example/example3.py
new file mode 100755
index 0000000..a889320
--- /dev/null
+++ b/example/example3.py
@@ -0,0 +1,22 @@
+#!/usr/bin/env python3
+import sys
+sys.path.append('.')
+
+from example import Vector2, Vector
+
+v1 = Vector2(1, 2)
+v2 = Vector(3, -1)
+
+print("v1    = " + str(v1))
+print("v2    = " + str(v2))
+print("v1+v2 = " + str(v1+v2))
+print("v1-v2 = " + str(v1-v2))
+print("v1-8  = " + str(v1-8))
+print("v1+8  = " + str(v1+8))
+print("v1*8  = " + str(v1*8))
+print("v1/8  = " + str(v1/8))
+
+v1 += v2
+v1 *= 2
+
+print("(v1+v2)*2 = " + str(v1))
diff --git a/example/example3.ref b/example/example3.ref
new file mode 100644
index 0000000..e45c110
--- /dev/null
+++ b/example/example3.ref
@@ -0,0 +1,37 @@
+Value constructor
+Value constructor
+Value constructor
+Copy constructor
+Destructor.
+Destructor.
+Value constructor
+Copy constructor
+Destructor.
+Destructor.
+Value constructor
+Copy constructor
+Destructor.
+Destructor.
+Value constructor
+Copy constructor
+Destructor.
+Destructor.
+Value constructor
+Copy constructor
+Destructor.
+Destructor.
+Value constructor
+Copy constructor
+Destructor.
+Destructor.
+v1    = [1.000000, 2.000000]
+v2    = [3.000000, -1.000000]
+v1+v2 = [4.000000, 1.000000]
+v1-v2 = [-2.000000, 3.000000]
+v1-8  = [-7.000000, -6.000000]
+v1+8  = [9.000000, 10.000000]
+v1*8  = [8.000000, 16.000000]
+v1/8  = [0.125000, 0.250000]
+(v1+v2)*2 = [8.000000, 2.000000]
+Destructor.
+Destructor.
diff --git a/example/example4.cpp b/example/example4.cpp
new file mode 100644
index 0000000..ed9d0da
--- /dev/null
+++ b/example/example4.cpp
@@ -0,0 +1,60 @@
+/*
+    example/example4.cpp -- Example 4: global constants and functions, enumerations
+
+    Copyright (c) 2015 Wenzel Jakob <wenzel@inf.ethz.ch>
+
+    All rights reserved. Use of this source code is governed by a
+    BSD-style license that can be found in the LICENSE file.
+*/
+
+#include "example.h"
+
+enum EMyEnumeration {
+    EFirstEntry = 1,
+    ESecondEntry
+};
+
+class Example4 {
+public:
+    enum EMode {
+        EFirstMode = 1,
+        ESecondMode
+    };
+
+    static void test_function(EMode mode) {
+        std::cout << "Example4::test_function(enum=" << mode << ")" << std::endl;
+    }
+};
+
+bool test_function1() {
+    std::cout << "test_function()" << std::endl;
+    return false;
+}
+
+float test_function2(int i) {
+    std::cout << "test_function(" << i << ")" << std::endl;
+    return i / 2.f;
+}
+
+void test_function3(EMyEnumeration k) {
+    std::cout << "test_function(enum=" << k << ")" << std::endl;
+}
+
+void init_ex4(py::module &m) {
+    m.def("test_function", &test_function1);
+    m.def("test_function", &test_function2);
+    m.def("test_function", &test_function3);
+    m.attr("some_constant") = py::int_(14);
+
+    py::enum_<EMyEnumeration>(m, "EMyEnumeration")
+        .value("EFirstEntry", EFirstEntry)
+        .value("ESecondEntry", ESecondEntry)
+        .export_values();
+
+    py::class_<Example4> ex4_class(m, "Example4");
+    ex4_class.def_static("test_function", &Example4::test_function);
+    py::enum_<Example4::EMode>(ex4_class, "EMode")
+        .value("EFirstMode", Example4::EFirstMode)
+        .value("ESecondMode", Example4::ESecondMode)
+        .export_values();
+}
diff --git a/example/example4.py b/example/example4.py
new file mode 100755
index 0000000..aa2a448
--- /dev/null
+++ b/example/example4.py
@@ -0,0 +1,24 @@
+#!/usr/bin/env python3
+import sys
+sys.path.append('.')
+
+from example import test_function
+from example import some_constant
+from example import EMyEnumeration
+from example import EFirstEntry
+from example import Example4
+
+print(EMyEnumeration)
+print(EMyEnumeration.EFirstEntry)
+print(EMyEnumeration.ESecondEntry)
+print(EFirstEntry)
+
+print(test_function())
+print(test_function(7))
+print(test_function(EMyEnumeration.EFirstEntry))
+print(test_function(EMyEnumeration.ESecondEntry))
+
+print(Example4.EMode)
+print(Example4.EMode.EFirstMode)
+print(Example4.EFirstMode)
+Example4.test_function(Example4.EFirstMode)
diff --git a/example/example4.ref b/example/example4.ref
new file mode 100644
index 0000000..09935a9
--- /dev/null
+++ b/example/example4.ref
@@ -0,0 +1,16 @@
+test_function()
+test_function(7)
+test_function(enum=1)
+test_function(enum=2)
+Example4::test_function(enum=1)
+<class 'example.EMyEnumeration'>
+EMyEnumeration.EFirstEntry
+EMyEnumeration.ESecondEntry
+EMyEnumeration.EFirstEntry
+False
+3.5
+None
+None
+<class 'example.Example4.EMode'>
+EMode.EFirstMode
+EMode.EFirstMode
diff --git a/example/example5.cpp b/example/example5.cpp
new file mode 100644
index 0000000..7d61779
--- /dev/null
+++ b/example/example5.cpp
@@ -0,0 +1,95 @@
+/*
+    example/example5.cpp -- Example 5: inheritance, callbacks, acquiring
+    and releasing the global interpreter lock
+
+    Copyright (c) 2015 Wenzel Jakob <wenzel@inf.ethz.ch>
+
+    All rights reserved. Use of this source code is governed by a
+    BSD-style license that can be found in the LICENSE file.
+*/
+
+#include "example.h"
+
+
+class Pet {
+public:
+    Pet(const std::string &name, const std::string &species)
+        : m_name(name), m_species(species) {}
+    std::string name() const { return m_name; }
+    std::string species() const { return m_species; }
+private:
+    std::string m_name;
+    std::string m_species;
+};
+
+class Dog : public Pet {
+public:
+    Dog(const std::string &name) : Pet(name, "dog") {}
+    void bark() const { std::cout << "Woof!" << std::endl; }
+};
+
+void pet_print(const Pet &pet) {
+    std::cout << pet.name() + " is a " + pet.species() << std::endl;
+}
+
+void dog_bark(const Dog &dog) {
+    dog.bark();
+}
+
+class Example5  {
+public:
+    Example5(py::handle self, int state)
+        : self(self), state(state) {
+        cout << "Constructing Example5.." << endl;
+    }
+
+    ~Example5() {
+        cout << "Destructing Example5.." << endl;
+    }
+
+    void callback(int value) {
+		py::gil_scoped_acquire gil;
+        cout << "In Example5::callback() " << endl;
+        py::object method = self.attr("callback");
+        method.call(state, value);
+    }
+private:
+    py::handle self;
+    int state;
+};
+
+bool test_callback1(py::object func) {
+    func.call();
+    return false;
+}
+
+int test_callback2(py::object func) {
+    py::object result = func.call("Hello", true, 5);
+    return result.cast<int>();
+}
+
+void test_callback3(Example5 *ex, int value) {
+	py::gil_scoped_release gil;
+    ex->callback(value);
+}
+
+void init_ex5(py::module &m) {
+    py::class_<Pet> pet_class(m, "Pet");
+    pet_class
+        .def(py::init<std::string, std::string>())
+        .def("name", &Pet::name)
+        .def("species", &Pet::species);
+
+    py::class_<Dog>(m, "Dog", pet_class)
+        .def(py::init<std::string>());
+
+    m.def("pet_print", pet_print);
+    m.def("dog_bark", dog_bark);
+
+    m.def("test_callback1", &test_callback1);
+    m.def("test_callback2", &test_callback2);
+    m.def("test_callback3", &test_callback3);
+
+    py::class_<Example5>(m, "Example5")
+        .def(py::init<py::object, int>());
+}
diff --git a/example/example5.py b/example/example5.py
new file mode 100755
index 0000000..b119de9
--- /dev/null
+++ b/example/example5.py
@@ -0,0 +1,45 @@
+#!/usr/bin/env python3
+import sys
+sys.path.append('.')
+
+from example import Pet
+from example import Dog
+from example import dog_bark
+from example import pet_print
+
+polly = Pet('Polly', 'parrot')
+molly = Dog('Molly')
+print(polly.name() + " is a " + polly.species())
+pet_print(polly)
+print(molly.name() + " is a " + molly.species())
+pet_print(molly)
+dog_bark(molly)
+try:
+    dog_bark(polly)
+except Exception as e:
+    print('The following error is expected: ' + str(e))
+
+from example import test_callback1
+from example import test_callback2
+from example import test_callback3
+from example import Example5
+
+def func1():
+    print('Callback function 1 called!')
+
+def func2(a, b, c):
+    print('Callback function 2 called : ' + str(a) + ", " + str(b) + ", "+ str(c))
+    return c
+
+class MyCallback(Example5):
+    def __init__(self, value):
+        Example5.__init__(self, self, value)
+
+    def callback(self, value1, value2):
+        print('got callback: %i %i' % (value1, value2))
+
+print(test_callback1(func1))
+print(test_callback2(func2))
+
+callback = MyCallback(3)
+test_callback3(callback, 4)
diff --git a/example/example5.ref b/example/example5.ref
new file mode 100644
index 0000000..4061128
--- /dev/null
+++ b/example/example5.ref
@@ -0,0 +1,16 @@
+Polly is a parrot
+Molly is a dog
+Woof!
+Constructing Example5..
+In Example5::callback() 
+Polly is a parrot
+Molly is a dog
+The following error is expected: Incompatible function arguments. The following argument types are supported:
+    1. dog_bark(Dog) -> None
+
+Callback function 1 called!
+False
+Callback function 2 called : Hello, True, 5
+5
+got callback: 3 4
+Destructing Example5..
diff --git a/example/example6.cpp b/example/example6.cpp
new file mode 100644
index 0000000..1e0359a
--- /dev/null
+++ b/example/example6.cpp
@@ -0,0 +1,175 @@
+/*
+    example/example6.cpp -- Example 6: supporting Pythons' sequence
+    protocol, iterators, etc.
+
+    Copyright (c) 2015 Wenzel Jakob <wenzel@inf.ethz.ch>
+
+    All rights reserved. Use of this source code is governed by a
+    BSD-style license that can be found in the LICENSE file.
+*/
+
+#include "example.h"
+#include <pybind/operators.h>
+
+class Sequence {
+public:
+    Sequence(size_t size) : m_size(size) {
+        std::cout << "Value constructor: Creating a sequence with " << m_size << " entries" << std::endl;
+        m_data = new float[size];
+        memset(m_data, 0, sizeof(float) * size);
+    }
+
+    Sequence(const std::vector<float> &value) : m_size(value.size()) {
+        std::cout << "Value constructor: Creating a sequence with " << m_size << " entries" << std::endl;
+        m_data = new float[m_size];
+        memcpy(m_data, &value[0], sizeof(float) * m_size);
+    }
+
+    Sequence(const Sequence &s) : m_size(s.m_size) {
+        std::cout << "Copy constructor: Creating a sequence with " << m_size << " entries" << std::endl;
+        m_data = new float[m_size];
+        memcpy(m_data, s.m_data, sizeof(float)*m_size);
+    }
+
+    Sequence(Sequence &&s) : m_size(s.m_size), m_data(s.m_data) {
+        std::cout << "Move constructor: Creating a sequence with " << m_size << " entries" << std::endl;
+        s.m_size = 0;
+        s.m_data = nullptr;
+    }
+
+    ~Sequence() {
+        std::cout << "Freeing a sequence with " << m_size << " entries" << std::endl;
+        delete[] m_data;
+    }
+
+    Sequence &operator=(const Sequence &s) {
+        std::cout << "Assignment operator: Creating a sequence with " << s.m_size << " entries" << std::endl;
+        delete[] m_data;
+        m_size = s.m_size;
+        m_data = new float[m_size];
+        memcpy(m_data, s.m_data, sizeof(float)*m_size);
+        return *this;
+    }
+
+    Sequence &operator=(Sequence &&s) {
+        std::cout << "Move assignment operator: Creating a sequence with " << s.m_size << " entries" << std::endl;
+        if (&s != this) {
+            delete[] m_data;
+            m_size = s.m_size;
+            m_data = s.m_data;
+            s.m_size = 0;
+            s.m_data = nullptr;
+        }
+        return *this;
+    }
+
+    bool operator==(const Sequence &s) const {
+        if (m_size != s.size())
+            return false;
+        for (size_t i=0; i<m_size; ++i)
+            if (m_data[i] != s[i])
+                return false;
+        return true;
+    }
+
+    bool operator!=(const Sequence &s) const {
+        return !operator==(s);
+    }
+
+    float operator[](size_t index) const {
+        return m_data[index];
+    }
+
+    float &operator[](size_t index) {
+        return m_data[index];
+    }
+
+    bool contains(float v) const {
+        for (size_t i=0; i<m_size; ++i)
+            if (v == m_data[i])
+                return true;
+        return false;
+    }
+
+    Sequence reversed() const {
+        Sequence result(m_size);
+        for (size_t i=0; i<m_size; ++i)
+            result[m_size-i-1] = m_data[i];
+        return result;
+    }
+
+    size_t size() const { return m_size; }
+
+private:
+    size_t m_size;
+    float *m_data;
+};
+
+namespace {
+    // Special iterator data structure for python
+    struct PySequenceIterator {
+        PySequenceIterator(const Sequence &seq, py::object ref) : seq(seq), ref(ref) { }
+
+        float next() {
+            if (index == seq.size())
+                throw py::stop_iteration();
+            return seq[index++];
+        }
+
+        const Sequence &seq;
+        py::object ref; // keep a reference
+        size_t index = 0;
+    };
+};
+
+void init_ex6(py::module &m) {
+    py::class_<Sequence> seq(m, "Sequence");
+
+    seq.def(py::init<size_t>())
+       .def(py::init<const std::vector<float>&>())
+       /// Bare bones interface
+       .def("__getitem__", [](const Sequence &s, size_t i) {
+            if (i >= s.size())
+                throw py::index_error();
+            return s[i];
+        })
+       .def("__setitem__", [](Sequence &s, size_t i, float v) {
+            if (i >= s.size())
+                throw py::index_error();
+            s[i] = v;
+        })
+       .def("__len__", &Sequence::size)
+       /// Optional sequence protocol operations
+       .def("__iter__", [](py::object s) { return PySequenceIterator(s.cast<const Sequence &>(), s); })
+       .def("__contains__", [](const Sequence &s, float v) { return s.contains(v); })
+       .def("__reversed__", [](const Sequence &s) -> Sequence { return s.reversed(); })
+       /// Slicing protocol (optional)
+       .def("__getitem__", [](const Sequence &s, py::slice slice) -> Sequence* {
+            py::ssize_t start, stop, step, slicelength;
+            if (!slice.compute(s.size(), &start, &stop, &step, &slicelength))
+                throw py::error_already_set();
+            Sequence *seq = new Sequence(slicelength);
+            for (int i=0; i<slicelength; ++i) {
+                (*seq)[i] = s[start]; start += step;
+            }
+            return seq;
+        })
+       .def("__setitem__", [](Sequence &s, py::slice slice, const Sequence &value) {
+            py::ssize_t start, stop, step, slicelength;
+            if (!slice.compute(s.size(), &start, &stop, &step, &slicelength))
+                throw py::error_already_set();
+            if ((size_t) slicelength != value.size())
+                throw std::runtime_error("Left and right hand size of slice assignment have different sizes!");
+            for (int i=0; i<slicelength; ++i) {
+                s[start] = value[i]; start += step;
+            }
+        })
+       /// Comparisons
+       .def(py::self == py::self)
+       .def(py::self != py::self);
+       // Could also define py::self + py::self for concatenation, etc.
+
+    py::class_<PySequenceIterator>(seq, "Iterator")
+        .def("__iter__", [](PySequenceIterator &it) -> PySequenceIterator& { return it; })
+        .def("__next__", &PySequenceIterator::next);
+}
diff --git a/example/example6.py b/example/example6.py
new file mode 100755
index 0000000..7dbadc4
--- /dev/null
+++ b/example/example6.py
@@ -0,0 +1,29 @@
+#!/usr/bin/env python3
+import sys
+sys.path.append('.')
+
+from example import Sequence
+
+s = Sequence(5)
+print("s = " + str(s))
+print("len(s) = " + str(len(s)))
+print("s[0], s[3] = %f %f" % (s[0], s[3]))
+print('12.34 in s: ' + str(12.34 in s))
+s[0], s[3] = 12.34, 56.78
+print('12.34 in s: ' + str(12.34 in s))
+print("s[0], s[3] = %f %f" % (s[0], s[3]))
+rev = reversed(s)
+rev2 = s[::-1]
+print("rev[0], rev[1], rev[2], rev[3], rev[4] = %f %f %f %f %f" % (rev[0], rev[1], rev[2], rev[3], rev[4]))
+
+for i in rev:
+    print(i, end=' ')
+print('')
+for i in rev2:
+    print(i, end=' ')
+print('')
+print(rev == rev2)
+rev[0::2] = Sequence([2.0, 2.0, 2.0])
+for i in rev:
+    print(i, end=' ')
+print('')
diff --git a/example/example6.ref b/example/example6.ref
new file mode 100644
index 0000000..8986be6
--- /dev/null
+++ b/example/example6.ref
@@ -0,0 +1,18 @@
+Value constructor: Creating a sequence with 5 entries
+Value constructor: Creating a sequence with 5 entries
+Copy constructor: Creating a sequence with 5 entries
+Freeing a sequence with 5 entries
+s = <example.Sequence object at 0x100380fb0>
+len(s) = 5
+s[0], s[3] = 0.000000 0.000000
+12.34 in s: False
+12.34 in s: True
+s[0], s[3] = 12.340000 56.779999
+rev[0], rev[1], rev[2], rev[3], rev[4] = 0.000000 56.779999 0.000000 0.000000 12.340000
+12.34000015258789
+0.0
+0.0
+56.779998779296875
+0.0
+Freeing a sequence with 5 entries
+Freeing a sequence with 5 entries
diff --git a/example/example7.cpp b/example/example7.cpp
new file mode 100644
index 0000000..82ab3b6
--- /dev/null
+++ b/example/example7.cpp
@@ -0,0 +1,115 @@
+/*
+    example/example7.cpp -- Example 7: supporting Pythons' buffer protocol
+
+    Copyright (c) 2015 Wenzel Jakob <wenzel@inf.ethz.ch>
+
+    All rights reserved. Use of this source code is governed by a
+    BSD-style license that can be found in the LICENSE file.
+*/
+
+#include "example.h"
+
+class Matrix {
+public:
+    Matrix(size_t rows, size_t cols) : m_rows(rows), m_cols(cols) {
+        std::cout << "Value constructor: Creating a " << rows << "x" << cols << " matrix " << std::endl;
+        m_data = new float[rows*cols];
+        memset(m_data, 0, sizeof(float) * rows * cols);
+    }
+
+    Matrix(const Matrix &s) : m_rows(s.m_rows), m_cols(s.m_cols) {
+        std::cout << "Copy constructor: Creating a " << m_rows << "x" << m_cols << " matrix " << std::endl;
+        m_data = new float[m_rows * m_cols];
+        memcpy(m_data, s.m_data, sizeof(float) * m_rows * m_cols);
+    }
+
+    Matrix(Matrix &&s) : m_rows(s.m_rows), m_cols(s.m_cols), m_data(s.m_data) {
+        std::cout << "Move constructor: Creating a " << m_rows << "x" << m_cols << " matrix " << std::endl;
+        s.m_rows = 0;
+        s.m_cols = 0;
+        s.m_data = nullptr;
+    }
+
+    ~Matrix() {
+        std::cout << "Freeing a " << m_rows << "x" << m_cols << " matrix " << std::endl;
+        delete[] m_data;
+    }
+
+    Matrix &operator=(const Matrix &s) {
+        std::cout << "Assignment operator : Creating a " << s.m_rows << "x" << s.m_cols << " matrix " << std::endl;
+        delete[] m_data;
+        m_rows = s.m_rows;
+        m_cols = s.m_cols;
+        m_data = new float[m_rows * m_cols];
+        memcpy(m_data, s.m_data, sizeof(float) * m_rows * m_cols);
+        return *this;
+    }
+
+    Matrix &operator=(Matrix &&s) {
+        std::cout << "Move assignment operator : Creating a " << s.m_rows << "x" << s.m_cols << " matrix " << std::endl;
+        if (&s != this) {
+            delete[] m_data;
+            m_rows = s.m_rows; m_cols = s.m_cols; m_data = s.m_data;
+            s.m_rows = 0; s.m_cols = 0; s.m_data = nullptr;
+        }
+        return *this;
+    }
+
+    float operator()(size_t i, size_t j) const {
+        return m_data[i*m_cols + j];
+    }
+
+    float &operator()(size_t i, size_t j) {
+        return m_data[i*m_cols + j];
+    }
+
+    float *data() { return m_data; }
+
+    size_t rows() const { return m_rows; }
+    size_t cols() const { return m_cols; }
+private:
+    size_t m_rows;
+    size_t m_cols;
+    float *m_data;
+};
+
+void init_ex7(py::module &m) {
+    py::class_<Matrix> mtx(m, "Matrix");
+
+    mtx.def(py::init<size_t, size_t>())
+        /// Construct from a buffer
+        .def("__init__", [](Matrix &v, py::buffer b) {
+            py::buffer_info info = b.request();
+            if (info.format != py::format_descriptor<float>::value() || info.ndim != 2)
+                throw std::runtime_error("Incompatible buffer format!");
+            new (&v) Matrix(info.shape[0], info.shape[1]);
+            memcpy(v.data(), info.ptr, sizeof(float) * v.rows() * v.cols());
+        })
+
+       .def("rows", &Matrix::rows)
+       .def("cols", &Matrix::cols)
+
+        /// Bare bones interface
+       .def("__getitem__", [](const Matrix &m, std::pair<size_t, size_t> i) {
+            if (i.first >= m.rows() || i.second >= m.cols())
+                throw py::index_error();
+            return m(i.first, i.second);
+        })
+       .def("__setitem__", [](Matrix &m, std::pair<size_t, size_t> i, float v) {
+            if (i.first >= m.rows() || i.second >= m.cols())
+                throw py::index_error();
+            m(i.first, i.second) = v;
+        })
+       /// Provide buffer access
+       .def_buffer([](Matrix &m) -> py::buffer_info {
+            return py::buffer_info(
+                m.data(),                              /* Pointer to buffer */
+                sizeof(float),                         /* Size of one scalar */
+                py::format_descriptor<float>::value(), /* Python struct-style format descriptor */
+                2,                                     /* Number of dimensions */
+                { m.rows(), m.cols() },                /* Buffer dimensions */
+                { sizeof(float) * m.rows(),            /* Strides (in bytes) for each index */
+                  sizeof(float) }
+            );
+        });
+}
diff --git a/example/example7.py b/example/example7.py
new file mode 100755
index 0000000..565ceac
--- /dev/null
+++ b/example/example7.py
@@ -0,0 +1,26 @@
+#!/usr/bin/env python3
+import sys
+sys.path.append('.')
+
+from example import Matrix
+import numpy as np
+
+m = Matrix(5, 5)
+
+print(m[2, 3])
+m[2, 3] = 4
+print(m[2, 3])
+
+m2 = np.array(m, copy=False)
+print(m2)
+print(m2[2, 3])
+m2[2, 3] = 5
+print(m[2, 3])
+
+m3 = np.array([[1,2,3],[4,5,6]]).astype(np.float32)
+print(m3)
+m4 = Matrix(m3)
+for i in range(m4.rows()):
+    for j in range(m4.cols()):
+        print(m4[i, j], end = ' ')
+    print()
diff --git a/example/example7.ref b/example/example7.ref
new file mode 100644
index 0000000..6112cf6
--- /dev/null
+++ b/example/example7.ref
@@ -0,0 +1,11 @@
+Value constructor: Creating a 5x5 matrix 
+0.0
+4.0
+[[ 0.  0.  0.  0.  0.]
+ [ 0.  0.  0.  0.  0.]
+ [ 0.  0.  0.  4.  0.]
+ [ 0.  0.  0.  0.  0.]
+ [ 0.  0.  0.  0.  0.]]
+4.0
+5.0
+Freeing a 5x5 matrix 
diff --git a/example/example8.cpp b/example/example8.cpp
new file mode 100644
index 0000000..3aac43a
--- /dev/null
+++ b/example/example8.cpp
@@ -0,0 +1,76 @@
+/*
+    example/example8.cpp -- Example 8: binding classes with
+    custom reference counting, implicit conversions between types
+
+    Copyright (c) 2015 Wenzel Jakob <wenzel@inf.ethz.ch>
+
+    All rights reserved. Use of this source code is governed by a
+    BSD-style license that can be found in the LICENSE file.
+*/
+
+#include "example.h"
+#include "object.h"
+
+/// Object subclass
+class MyObject : public Object {
+public:
+    MyObject(int value) : value(value) {
+        std::cout << toString() << " constructor" << std::endl;
+    }
+
+    std::string toString() const {
+        return "MyObject[" + std::to_string(value) + "]";
+    }
+
+protected:
+    virtual ~MyObject() {
+        std::cout << toString() << " destructor" << std::endl;
+    }
+
+private:
+    int value;
+};
+
+/// Make pybind aware of the ref-counted wrapper type
+namespace pybind { namespace detail {
+template <typename T> class type_caster<ref<T>>
+    : public type_caster_holder<T, ref<T>> { };
+}}
+
+Object *make_object_1() { return new MyObject(1); }
+ref<Object> make_object_2() { return new MyObject(2); }
+MyObject *make_myobject_4() { return new MyObject(4); }
+ref<MyObject> make_myobject_5() { return new MyObject(5); }
+
+void print_object_1(const Object *obj) { std::cout << obj->toString() << std::endl; }
+void print_object_2(ref<Object> obj) { std::cout << obj->toString() << std::endl; }
+void print_object_3(const ref<Object> &obj) { std::cout << obj->toString() << std::endl; }
+void print_object_4(const ref<Object> *obj) { std::cout << (*obj)->toString() << std::endl; }
+
+void print_myobject_1(const MyObject *obj) { std::cout << obj->toString() << std::endl; }
+void print_myobject_2(ref<MyObject> obj) { std::cout << obj->toString() << std::endl; }
+void print_myobject_3(const ref<MyObject> &obj) { std::cout << obj->toString() << std::endl; }
+void print_myobject_4(const ref<MyObject> *obj) { std::cout << (*obj)->toString() << std::endl; }
+
+void init_ex8(py::module &m) {
+    py::class_<Object, ref<Object>> obj(m, "Object");
+    obj.def("getRefCount", &Object::getRefCount);
+
+    py::class_<MyObject, ref<MyObject>>(m, "MyObject", obj)
+        .def(py::init<int>());
+
+    m.def("make_object_1", &make_object_1);
+    m.def("make_object_2", &make_object_2);
+    m.def("make_myobject_4", &make_myobject_4);
+    m.def("make_myobject_5", &make_myobject_5);
+    m.def("print_object_1", &print_object_1);
+    m.def("print_object_2", &print_object_2);
+    m.def("print_object_3", &print_object_3);
+    m.def("print_object_4", &print_object_4);
+    m.def("print_myobject_1", &print_myobject_1);
+    m.def("print_myobject_2", &print_myobject_2);
+    m.def("print_myobject_3", &print_myobject_3);
+    m.def("print_myobject_4", &print_myobject_4);
+
+    py::implicitly_convertible<py::int_, MyObject>();
+}
diff --git a/example/example8.py b/example/example8.py
new file mode 100644
index 0000000..9c295d2
--- /dev/null
+++ b/example/example8.py
@@ -0,0 +1,36 @@
+#!/usr/bin/env python3
+import sys
+sys.path.append('.')
+
+from example import MyObject
+from example import make_object_1
+from example import make_object_2
+from example import make_myobject_4
+from example import make_myobject_5
+from example import print_object_1
+from example import print_object_2
+from example import print_object_3
+from example import print_object_4
+from example import print_myobject_1
+from example import print_myobject_2
+from example import print_myobject_3
+from example import print_myobject_4
+
+for o in [make_object_1(), make_object_2(), MyObject(3)]:
+    print("Reference count = %i" % o.getRefCount())
+    print_object_1(o)
+    print_object_2(o)
+    print_object_3(o)
+    print_object_4(o)
+
+for o in [make_myobject_4(), make_myobject_5(), MyObject(6), 7]:
+    print(o)
+    if not isinstance(o, int):
+        print_object_1(o)
+        print_object_2(o)
+        print_object_3(o)
+        print_object_4(o)
+    print_myobject_1(o)
+    print_myobject_2(o)
+    print_myobject_3(o)
+    print_myobject_4(o)
diff --git a/example/example9.cpp b/example/example9.cpp
new file mode 100644
index 0000000..0e070b1
--- /dev/null
+++ b/example/example9.cpp
@@ -0,0 +1,53 @@
+/*
+    example/example9.cpp -- Example 9: nested modules
+    and internal references
+
+    Copyright (c) 2015 Wenzel Jakob <wenzel@inf.ethz.ch>
+
+    All rights reserved. Use of this source code is governed by a
+    BSD-style license that can be found in the LICENSE file.
+*/
+
+#include "example.h"
+
+void submodule_func() {
+    std::cout << "submodule_func()" << std::endl;
+}
+
+class A {
+public:
+    A(int v) : v(v) { std::cout << "A constructor" << std::endl; }
+    ~A() { std::cout << "A destructor" << std::endl; }
+    A(const A&) { std::cout << "A copy constructor" << std::endl; }
+    std::string toString() { return "A[" + std::to_string(v) + "]"; }
+private:
+    int v;
+};
+
+class B {
+public:
+    B() { std::cout << "B constructor" << std::endl; }
+    ~B() { std::cout << "B destructor" << std::endl; }
+    B(const B&) { std::cout << "B copy constructor" << std::endl; }
+    A &get_a1() { return a1; }
+    A &get_a2() { return a2; }
+
+    A a1{1};
+    A a2{2};
+};
+
+void init_ex9(py::module &m) {
+    py::module m_sub = m.def_submodule("submodule");
+    m_sub.def("submodule_func", &submodule_func);
+
+    py::class_<A>(m_sub, "A")
+        .def(py::init<int>())
+        .def("__repr__", &A::toString);
+
+    py::class_<B>(m_sub, "B")
+        .def(py::init<>())
+        .def("get_a1", &B::get_a1, "Return the internal A 1", py::return_value_policy::reference_internal)
+        .def("get_a2", &B::get_a2, "Return the internal A 2", py::return_value_policy::reference_internal)
+        .def_readwrite("a1", &B::a1)  // def_readonly uses an internal reference return policy by default
+        .def_readwrite("a2", &B::a2);
+}
diff --git a/example/example9.py b/example/example9.py
new file mode 100644
index 0000000..d8c654e
--- /dev/null
+++ b/example/example9.py
@@ -0,0 +1,27 @@
+#!/usr/bin/env python3
+import sys
+sys.path.append('.')
+
+import example
+
+print(example.__name__)
+print(example.submodule.__name__)
+
+from example.submodule import *
+
+submodule_func()
+
+b = B()
+print(b.get_a1())
+print(b.a1)
+print(b.get_a2())
+print(b.a2)
+
+b.a1 = A(42)
+b.a2 = A(43)
+
+print(b.get_a1())
+print(b.a1)
+print(b.get_a2())
+print(b.a2)
+
diff --git a/example/object.h b/example/object.h
new file mode 100644
index 0000000..8097bd6
--- /dev/null
+++ b/example/object.h
@@ -0,0 +1,160 @@
+#if !defined(__OBJECT_H)
+#define __OBJECT_H
+
+#include <atomic>
+
+/// Reference counted object base class
+class Object {
+public:
+    /// Default constructor
+    Object() { }
+
+    /// Copy constructor
+    Object(const Object &) : m_refCount(0) {}
+
+	/// Return the current reference count
+	int getRefCount() const { return m_refCount; };
+
+	/// Increase the object's reference count by one
+	void incRef() const { ++m_refCount; }
+
+	/** \brief Decrease the reference count of
+	 * the object and possibly deallocate it.
+	 *
+	 * The object will automatically be deallocated once
+	 * the reference count reaches zero.
+	 */
+	void decRef(bool dealloc = true) const {
+	    --m_refCount;
+	    if (m_refCount == 0 && dealloc)
+            delete this;
+        else if (m_refCount < 0)
+	        throw std::runtime_error("Internal error: reference count < 0!");
+    }
+
+    virtual std::string toString() const = 0;
+protected:
+	/** \brief Virtual protected deconstructor.
+	 * (Will only be called by \ref ref)
+	 */
+	virtual ~Object() { }
+private:
+    mutable std::atomic<int> m_refCount { 0 };
+};
+
+/**
+ * \brief Reference counting helper
+ *
+ * The \a ref refeference template is a simple wrapper to store a
+ * pointer to an object. It takes care of increasing and decreasing
+ * the reference count of the object. When the last reference goes
+ * out of scope, the associated object will be deallocated.
+ *
+ * \ingroup libcore
+ */
+template <typename T> class ref {
+public:
+	/// Create a nullptr reference
+    ref() : m_ptr(nullptr) { std::cout << "Created empty ref" << std::endl; }
+
+    /// Construct a reference from a pointer
+	ref(T *ptr) : m_ptr(ptr) {
+        std::cout << "Initialized ref from pointer " << ptr<< std::endl;
+	    if (m_ptr) ((Object *) m_ptr)->incRef();
+	}
+
+	/// Copy constructor
+    ref(const ref &r) : m_ptr(r.m_ptr) {
+        std::cout << "Initialized ref from ref " << r.m_ptr << std::endl;
+        if (m_ptr)
+            ((Object *) m_ptr)->incRef();
+    }
+
+    /// Move constructor
+    ref(ref &&r) : m_ptr(r.m_ptr) {
+        std::cout << "Initialized ref with move from ref " << r.m_ptr << std::endl;
+        r.m_ptr = nullptr; 
+    }
+
+    /// Destroy this reference
+    ~ref() {
+        std::cout << "Destructing ref " << m_ptr << std::endl;
+        if (m_ptr)
+            ((Object *) m_ptr)->decRef();
+    }
+
+    /// Move another reference into the current one
+	ref& operator=(ref&& r) {
+        std::cout << "Move-assigning ref " << r.m_ptr << std::endl;
+		if (*this == r)
+			return *this;
+		if (m_ptr)
+			((Object *) m_ptr)->decRef();
+		m_ptr = r.m_ptr;
+		r.m_ptr = nullptr;
+		return *this;
+	}
+
+	/// Overwrite this reference with another reference
+	ref& operator=(const ref& r) {
+        std::cout << "Assigning ref " << r.m_ptr << std::endl;
+		if (m_ptr == r.m_ptr)
+			return *this;
+		if (m_ptr)
+			((Object *) m_ptr)->decRef();
+		m_ptr = r.m_ptr;
+		if (m_ptr)
+			((Object *) m_ptr)->incRef();
+		return *this;
+	}
+
+	/// Overwrite this reference with a pointer to another object
+	ref& operator=(T *ptr) {
+        std::cout << "Assigning ptr " << ptr << " to ref" << std::endl;
+		if (m_ptr == ptr)
+			return *this;
+		if (m_ptr)
+			((Object *) m_ptr)->decRef();
+		m_ptr = ptr;
+		if (m_ptr)
+			((Object *) m_ptr)->incRef();
+		return *this;
+	}
+
+	/// Compare this reference with another reference
+	bool operator==(const ref &r) const { return m_ptr == r.m_ptr; }
+
+	/// Compare this reference with another reference
+	bool operator!=(const ref &r) const { return m_ptr != r.m_ptr; }
+
+	/// Compare this reference with a pointer
+	bool operator==(const T* ptr) const { return m_ptr == ptr; }
+
+	/// Compare this reference with a pointer
+	bool operator!=(const T* ptr) const { return m_ptr != ptr; }
+
+	/// Access the object referenced by this reference
+	T* operator->() { return m_ptr; }
+
+	/// Access the object referenced by this reference
+	const T* operator->() const { return m_ptr; }
+
+	/// Return a C++ reference to the referenced object
+	T& operator*() { return *m_ptr; }
+
+	/// Return a const C++ reference to the referenced object
+	const T& operator*() const { return *m_ptr; }
+
+	/// Return a pointer to the referenced object
+	operator T* () { return m_ptr; }
+
+	/// Return a const pointer to the referenced object
+	T* get() { return m_ptr; }
+
+	/// Return a pointer to the referenced object
+	const T* get() const { return m_ptr; }
+private:
+	T *m_ptr;
+};
+
+#endif /* __OBJECT_H */
diff --git a/example/run_test.py b/example/run_test.py
new file mode 100644
index 0000000..1c47cc0
--- /dev/null
+++ b/example/run_test.py
@@ -0,0 +1,16 @@
+import subprocess, sys, os
+
+path = os.path.dirname(__file__)
+if path != '':
+    os.chdir(path)
+
+name = sys.argv[1]
+output    = subprocess.check_output([sys.executable, name + ".py"]).decode('utf-8')
+reference = open(name + '.ref', 'r').read()
+
+if output == reference:
+    print('Test "%s" succeeded.' % name)
+    exit(0)
+else:
+    print('Test "%s" FAILED!' % name)
+    exit(-1)