blob: afb864db29e8eaea00f4bd98445d1b62fccc28fa [file] [log] [blame]
Wenzel Jakob38bd7112015-07-05 20:05:44 +02001/*
Jason Rhinelanderb3f3d792016-07-18 16:43:18 -04002 example/example-callbacks.cpp -- callbacks
Wenzel Jakob38bd7112015-07-05 20:05:44 +02003
Wenzel Jakob8cb6cb32016-04-17 20:21:41 +02004 Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
Wenzel Jakob38bd7112015-07-05 20:05:44 +02005
6 All rights reserved. Use of this source code is governed by a
7 BSD-style license that can be found in the LICENSE file.
8*/
9
10#include "example.h"
Jason Rhinelander3f589372016-08-07 13:05:26 -040011#include "constructor-stats.h"
Wenzel Jakob8f4eb002015-10-15 18:13:33 +020012#include <pybind11/functional.h>
Wenzel Jakob38bd7112015-07-05 20:05:44 +020013
14
Wenzel Jakob38bd7112015-07-05 20:05:44 +020015bool test_callback1(py::object func) {
Wenzel Jakob6c03beb2016-05-08 14:34:09 +020016 func();
Wenzel Jakob38bd7112015-07-05 20:05:44 +020017 return false;
18}
19
20int test_callback2(py::object func) {
Wenzel Jakob6c03beb2016-05-08 14:34:09 +020021 py::object result = func("Hello", 'x', true, 5);
Wenzel Jakob38bd7112015-07-05 20:05:44 +020022 return result.cast<int>();
23}
24
Wenzel Jakoba2f6fde2015-10-01 16:46:03 +020025void test_callback3(const std::function<int(int)> &func) {
Wenzel Jakob281aa0e2015-07-30 15:29:00 +020026 cout << "func(43) = " << func(43)<< std::endl;
27}
28
Wenzel Jakoba2f6fde2015-10-01 16:46:03 +020029std::function<int(int)> test_callback4() {
Wenzel Jakob281aa0e2015-07-30 15:29:00 +020030 return [](int i) { return i+1; };
31}
32
Brad Harmon835fc062016-06-16 13:19:15 -050033py::cpp_function test_callback5() {
34 return py::cpp_function([](int i) { return i+1; },
35 py::arg("number"));
36}
37
Wenzel Jakob954b7932016-07-10 10:13:18 +020038int dummy_function(int i) { return i + 1; }
39int dummy_function2(int i, int j) { return i + j; }
40std::function<int(int)> roundtrip(std::function<int(int)> f) {
41 std::cout << "roundtrip.." << std::endl;
42 return f;
43}
44
45void test_dummy_function(const std::function<int(int)> &f) {
46 using fn_type = int (*)(int);
47 auto result = f.target<fn_type>();
48 if (!result) {
49 std::cout << "could not convert to a function pointer." << std::endl;
50 auto r = f(1);
51 std::cout << "eval(1) = " << r << std::endl;
52 } else if (*result == dummy_function) {
53 std::cout << "argument matches dummy_function" << std::endl;
54 auto r = (*result)(1);
55 std::cout << "eval(1) = " << r << std::endl;
56 } else {
57 std::cout << "argument does NOT match dummy_function. This should never happen!" << std::endl;
58 }
59}
60
Jason Rhinelander3f589372016-08-07 13:05:26 -040061struct Payload {
62 Payload() {
63 print_default_created(this);
64 }
65 ~Payload() {
66 print_destroyed(this);
67 }
68 Payload(const Payload &) {
69 print_copy_created(this);
70 }
71 Payload(Payload &&) {
72 print_move_created(this);
73 }
74};
75
Jason Rhinelanderb3f3d792016-07-18 16:43:18 -040076void init_ex_callbacks(py::module &m) {
Wenzel Jakob38bd7112015-07-05 20:05:44 +020077 m.def("test_callback1", &test_callback1);
78 m.def("test_callback2", &test_callback2);
79 m.def("test_callback3", &test_callback3);
Wenzel Jakob281aa0e2015-07-30 15:29:00 +020080 m.def("test_callback4", &test_callback4);
Brad Harmon835fc062016-06-16 13:19:15 -050081 m.def("test_callback5", &test_callback5);
Wenzel Jakob19208fe2015-10-13 17:37:25 +020082
83 /* Test cleanup of lambda closure */
84
Wenzel Jakob19208fe2015-10-13 17:37:25 +020085 m.def("test_cleanup", []() -> std::function<void(void)> {
86 Payload p;
87
88 return [p]() {
89 /* p should be cleaned up when the returned function is garbage collected */
90 };
91 });
Wenzel Jakob954b7932016-07-10 10:13:18 +020092
93 /* Test if passing a function pointer from C++ -> Python -> C++ yields the original pointer */
94 m.def("dummy_function", &dummy_function);
95 m.def("dummy_function2", &dummy_function2);
96 m.def("roundtrip", &roundtrip);
97 m.def("test_dummy_function", &test_dummy_function);
Jason Rhinelander3f589372016-08-07 13:05:26 -040098 // Export the payload constructor statistics for testing purposes:
99 m.def("payload_cstats", &ConstructorStats::get<Payload>);
Wenzel Jakob38bd7112015-07-05 20:05:44 +0200100}