issues.cpp 4.82 KB
Newer Older
1
2
3
/*
    example/issues.cpp -- collection of testcases for miscellaneous issues

4
    Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
5
6
7
8
9
10

    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"
11
#include <pybind11/stl.h>
12

Wenzel Jakob's avatar
Wenzel Jakob committed
13
14
PYBIND11_DECLARE_HOLDER_TYPE(T, std::shared_ptr<T>);

15
16
17
void init_issues(py::module &m) {
    py::module m2 = m.def_submodule("issues");

Wenzel Jakob's avatar
Wenzel Jakob committed
18
19
20
21
22
23
#if !defined(_MSC_VER)
    // Visual Studio 2015 currently cannot compile this test
    // (see the comment in type_caster_base::make_copy_constructor)
    // #70 compilation issue if operator new is not public
    class NonConstructible { private: void *operator new(size_t bytes) throw(); };
    py::class_<NonConstructible>(m, "Foo");
24
    m2.def("getstmt", []() -> NonConstructible * { return nullptr; },
Wenzel Jakob's avatar
Wenzel Jakob committed
25
26
27
        py::return_value_policy::reference);
#endif

28
29
    // #137: const char* isn't handled properly
    m2.def("print_cchar", [](const char *string) { std::cout << string << std::endl; });
30
31
32

    // #150: char bindings broken
    m2.def("print_char", [](char c) { std::cout << c << std::endl; });
33
34

    // #159: virtual function dispatch has problems with similar-named functions
Wenzel Jakob's avatar
Wenzel Jakob committed
35
36
37
    struct Base { virtual void dispatch(void) const {
        /* for some reason MSVC2015 can't compile this if the function is pure virtual */
    }; };
Wenzel Jakob's avatar
Wenzel Jakob committed
38
39
40
41
42
43
44

    struct DispatchIssue : Base {
        virtual void dispatch(void) const {
            PYBIND11_OVERLOAD_PURE(void, Base, dispatch, /* no arguments */);
        }
    };

45
    py::class_<Base, std::unique_ptr<Base>, DispatchIssue>(m2, "DispatchIssue")
46
        .def(py::init<>())
47
48
        .def("dispatch", &Base::dispatch);

Wenzel Jakob's avatar
Wenzel Jakob committed
49
50
51
    m2.def("dispatch_issue_go", [](const Base * b) { b->dispatch(); });

    struct Placeholder { int i; Placeholder(int i) : i(i) { } };
52
53

    py::class_<Placeholder>(m2, "Placeholder")
54
        .def(py::init<int>())
55
56
57
        .def("__repr__", [](const Placeholder &p) { return "Placeholder[" + std::to_string(p.i) + "]"; });

    // #171: Can't return reference wrappers (or STL datastructures containing them)
58
    m2.def("return_vec_of_reference_wrapper", [](std::reference_wrapper<Placeholder> p4){
59
60
        Placeholder *p1 = new Placeholder{1};
        Placeholder *p2 = new Placeholder{2};
61
        Placeholder *p3 = new Placeholder{3};
62
63
64
65
        std::vector<std::reference_wrapper<Placeholder>> v;
        v.push_back(std::ref(*p1));
        v.push_back(std::ref(*p2));
        v.push_back(std::ref(*p3));
66
        v.push_back(p4);
67
68
        return v;
    });
69
70
71
72
73

    // #181: iterator passthrough did not compile
    m2.def("iterator_passthrough", [](py::iterator s) -> py::iterator {
        return py::make_iterator(std::begin(s), std::end(s));
    });
Wenzel Jakob's avatar
Wenzel Jakob committed
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102

    // #187: issue involving std::shared_ptr<> return value policy & garbage collection
    struct ElementBase { virtual void foo() { } /* Force creation of virtual table */ };
    struct ElementA : ElementBase {
        ElementA(int v) : v(v) { }
        int value() { return v; }
        int v;
    };

    struct ElementList {
        void add(std::shared_ptr<ElementBase> e) { l.push_back(e); }
        std::vector<std::shared_ptr<ElementBase>> l;
    };

    py::class_<ElementBase, std::shared_ptr<ElementBase>> (m2, "ElementBase");

    py::class_<ElementA, std::shared_ptr<ElementA>>(m2, "ElementA", py::base<ElementBase>())
        .def(py::init<int>())
        .def("value", &ElementA::value);

    py::class_<ElementList, std::shared_ptr<ElementList>>(m2, "ElementList")
        .def(py::init<>())
        .def("add", &ElementList::add)
        .def("get", [](ElementList &el){
            py::list list;
            for (auto &e : el.l)
                list.append(py::cast(e));
            return list;
        });
103
104
105

    // (no id): should not be able to pass 'None' to a reference argument
    m2.def("print_element", [](ElementA &el) { std::cout << el.value() << std::endl; });
106
107
108
109

    // (no id): don't cast doubles to ints
    m2.def("expect_float", [](float f) { return f; });
    m2.def("expect_int", [](int i) { return i; });
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133

    // (no id): don't invoke Python dispatch code when instantiating C++
    // classes that were not extended on the Python side
    struct A {
        virtual ~A() {}
        virtual void f() { std::cout << "A.f()" << std::endl; }
    };

    struct PyA : A {
        PyA() { std::cout << "PyA.PyA()" << std::endl; }

        void f() override {
            std::cout << "PyA.f()" << std::endl;
            PYBIND11_OVERLOAD(void, A, f);
        }
    };

    auto call_f = [](A *a) { a->f(); };

	pybind11::class_<A, std::unique_ptr<A>, PyA>(m2, "A")
	    .def(py::init<>())
	    .def("f", &A::f);

	 m2.def("call_f", call_f);
134
135
136
137
138
139
140

    try {
        py::class_<Placeholder>(m2, "Placeholder");
        throw std::logic_error("Expected an exception!");
    } catch (std::runtime_error &e) {
        /* All good */
    }
141
}