blob: 3c144f220965e9887c177fd61d46647d61670134 [file] [log] [blame]
Wenzel Jakob38bd7112015-07-05 20:05:44 +02001/*
Wenzel Jakoba576e6a2015-07-29 17:51:54 +02002 example/example5.cpp -- inheritance, callbacks, acquiring and releasing the
3 global interpreter lock
Wenzel Jakob38bd7112015-07-05 20:05:44 +02004
Wenzel Jakob8cb6cb32016-04-17 20:21:41 +02005 Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
Wenzel Jakob38bd7112015-07-05 20:05:44 +02006
7 All rights reserved. Use of this source code is governed by a
8 BSD-style license that can be found in the LICENSE file.
9*/
10
11#include "example.h"
Wenzel Jakob8f4eb002015-10-15 18:13:33 +020012#include <pybind11/functional.h>
Wenzel Jakob38bd7112015-07-05 20:05:44 +020013
14
15class Pet {
16public:
17 Pet(const std::string &name, const std::string &species)
18 : m_name(name), m_species(species) {}
19 std::string name() const { return m_name; }
20 std::string species() const { return m_species; }
21private:
22 std::string m_name;
23 std::string m_species;
24};
25
26class Dog : public Pet {
27public:
28 Dog(const std::string &name) : Pet(name, "dog") {}
29 void bark() const { std::cout << "Woof!" << std::endl; }
30};
31
Wenzel Jakob48548ea2016-01-17 22:36:44 +010032class Rabbit : public Pet {
33public:
34 Rabbit(const std::string &name) : Pet(name, "parrot") {}
35};
36
Wenzel Jakob38bd7112015-07-05 20:05:44 +020037void pet_print(const Pet &pet) {
38 std::cout << pet.name() + " is a " + pet.species() << std::endl;
39}
40
41void dog_bark(const Dog &dog) {
42 dog.bark();
43}
44
Wenzel Jakob38bd7112015-07-05 20:05:44 +020045bool test_callback1(py::object func) {
Wenzel Jakob6c03beb2016-05-08 14:34:09 +020046 func();
Wenzel Jakob38bd7112015-07-05 20:05:44 +020047 return false;
48}
49
50int test_callback2(py::object func) {
Wenzel Jakob6c03beb2016-05-08 14:34:09 +020051 py::object result = func("Hello", 'x', true, 5);
Wenzel Jakob38bd7112015-07-05 20:05:44 +020052 return result.cast<int>();
53}
54
Wenzel Jakoba2f6fde2015-10-01 16:46:03 +020055void test_callback3(const std::function<int(int)> &func) {
Wenzel Jakob281aa0e2015-07-30 15:29:00 +020056 cout << "func(43) = " << func(43)<< std::endl;
57}
58
Wenzel Jakoba2f6fde2015-10-01 16:46:03 +020059std::function<int(int)> test_callback4() {
Wenzel Jakob281aa0e2015-07-30 15:29:00 +020060 return [](int i) { return i+1; };
61}
62
Brad Harmon835fc062016-06-16 13:19:15 -050063py::cpp_function test_callback5() {
64 return py::cpp_function([](int i) { return i+1; },
65 py::arg("number"));
66}
67
Wenzel Jakob954b7932016-07-10 10:13:18 +020068int dummy_function(int i) { return i + 1; }
69int dummy_function2(int i, int j) { return i + j; }
70std::function<int(int)> roundtrip(std::function<int(int)> f) {
71 std::cout << "roundtrip.." << std::endl;
72 return f;
73}
74
75void test_dummy_function(const std::function<int(int)> &f) {
76 using fn_type = int (*)(int);
77 auto result = f.target<fn_type>();
78 if (!result) {
79 std::cout << "could not convert to a function pointer." << std::endl;
80 auto r = f(1);
81 std::cout << "eval(1) = " << r << std::endl;
82 } else if (*result == dummy_function) {
83 std::cout << "argument matches dummy_function" << std::endl;
84 auto r = (*result)(1);
85 std::cout << "eval(1) = " << r << std::endl;
86 } else {
87 std::cout << "argument does NOT match dummy_function. This should never happen!" << std::endl;
88 }
89}
90
Wenzel Jakob38bd7112015-07-05 20:05:44 +020091void init_ex5(py::module &m) {
92 py::class_<Pet> pet_class(m, "Pet");
93 pet_class
94 .def(py::init<std::string, std::string>())
95 .def("name", &Pet::name)
96 .def("species", &Pet::species);
97
Wenzel Jakob48548ea2016-01-17 22:36:44 +010098 /* One way of declaring a subclass relationship: reference parent's class_ object */
Wenzel Jakob38bd7112015-07-05 20:05:44 +020099 py::class_<Dog>(m, "Dog", pet_class)
100 .def(py::init<std::string>());
101
Wenzel Jakob48548ea2016-01-17 22:36:44 +0100102 /* Another way of declaring a subclass relationship: reference parent's C++ type */
103 py::class_<Rabbit>(m, "Rabbit", py::base<Pet>())
104 .def(py::init<std::string>());
105
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200106 m.def("pet_print", pet_print);
107 m.def("dog_bark", dog_bark);
108
109 m.def("test_callback1", &test_callback1);
110 m.def("test_callback2", &test_callback2);
111 m.def("test_callback3", &test_callback3);
Wenzel Jakob281aa0e2015-07-30 15:29:00 +0200112 m.def("test_callback4", &test_callback4);
Brad Harmon835fc062016-06-16 13:19:15 -0500113 m.def("test_callback5", &test_callback5);
Wenzel Jakob19208fe2015-10-13 17:37:25 +0200114
115 /* Test cleanup of lambda closure */
116
117 struct Payload {
118 Payload() {
119 std::cout << "Payload constructor" << std::endl;
120 }
121 ~Payload() {
122 std::cout << "Payload destructor" << std::endl;
123 }
124 Payload(const Payload &) {
125 std::cout << "Payload copy constructor" << std::endl;
126 }
127 Payload(Payload &&) {
128 std::cout << "Payload move constructor" << std::endl;
129 }
130 };
131
132 m.def("test_cleanup", []() -> std::function<void(void)> {
133 Payload p;
134
135 return [p]() {
136 /* p should be cleaned up when the returned function is garbage collected */
137 };
138 });
Wenzel Jakob954b7932016-07-10 10:13:18 +0200139
140 /* Test if passing a function pointer from C++ -> Python -> C++ yields the original pointer */
141 m.def("dummy_function", &dummy_function);
142 m.def("dummy_function2", &dummy_function2);
143 m.def("roundtrip", &roundtrip);
144 m.def("test_dummy_function", &test_dummy_function);
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200145}