Sfoglia il codice sorgente

fix memory leak in property and staticmethod. (#301)

* fix memory leak in property and staticmethod.

* some format.
ykiko 1 anno fa
parent
commit
9564013c1d

+ 3 - 13
include/pybind11/internal/function.h

@@ -585,24 +585,14 @@ class cpp_function : public function {
 class property : public object {
     PKBIND_TYPE_IMPL(object, property, tp_property);
 
-    property(handle getter, handle setter = none()) : object() {
-        auto start = py_peek(0);
-        py_push(getter.ptr());
-        py_push(setter.ptr());
-        raise_call<py_tpcall>(type::of<property>().index(), 2, start);
-        *this = object::from_ret();
-    }
+    property(handle getter, handle setter = none()) :
+        object(type::of<property>()(getter, setter)) {}
 };
 
 class staticmethod : public object {
     PKBIND_TYPE_IMPL(object, staticmethod, tp_staticmethod);
 
-    staticmethod(handle method) : object() {
-        auto start = py_peek(0);
-        py_push(method.ptr());
-        raise_call<py_tpcall>(type::of<staticmethod>().index(), 1, start);
-        *this = object::from_ret();
-    }
+    staticmethod(handle method) : object(type::of<staticmethod>()(method)) {}
 };
 
 namespace impl {

+ 55 - 14
include/pybind11/tests/operators.cpp

@@ -1,5 +1,5 @@
 #include "test.h"
-#include <pybind11/operators.h>
+#include "pybind11/operators.h"
 
 namespace {
 
@@ -8,19 +8,19 @@ struct Int {
 
     Int(int x) : x(x) {}
 
-#define OPERATOR_IMPL(op)                                                                                              \
-    template <typename LHS, typename RHS>                                                                              \
-    friend int operator op (const LHS& lhs, const RHS& rhs) {                                                          \
-        int l, r;                                                                                                      \
-        if constexpr(std::is_same_v<LHS, Int>)                                                                         \
-            l = lhs.x;                                                                                                 \
-        else                                                                                                           \
-            l = lhs;                                                                                                   \
-        if constexpr(std::is_same_v<RHS, Int>)                                                                         \
-            r = rhs.x;                                                                                                 \
-        else                                                                                                           \
-            r = rhs;                                                                                                   \
-        return l op r;                                                                                                 \
+#define OPERATOR_IMPL(op)                                                                          \
+    template <typename LHS, typename RHS>                                                          \
+    friend int operator op (const LHS& lhs, const RHS& rhs) {                                      \
+        int l, r;                                                                                  \
+        if constexpr(std::is_same_v<LHS, Int>)                                                     \
+            l = lhs.x;                                                                             \
+        else                                                                                       \
+            l = lhs;                                                                               \
+        if constexpr(std::is_same_v<RHS, Int>)                                                     \
+            r = rhs.x;                                                                             \
+        else                                                                                       \
+            r = rhs;                                                                               \
+        return l op r;                                                                             \
     }
 
     OPERATOR_IMPL(+)
@@ -148,3 +148,44 @@ TEST_F(PYBIND11_TEST, logic_operators) {
     EXPECT_FALSE(a >= b);
 }
 
+TEST_F(PYBIND11_TEST, item_operators) {
+    py::module_ m = py::module_::import("__main__");
+
+    py::class_<std::vector<int>>(m, "vector")
+        .def(py::init<>())
+        .def("__getitem__",
+             [](std::vector<int>& v, int i) {
+                 return v[i];
+             })
+        .def("__setitem__",
+             [](std::vector<int>& v, int i, int x) {
+                 v[i] = x;
+             })
+        .def("push_back",
+             [](std::vector<int>& v, int x) {
+                 v.push_back(x);
+             })
+        .def("__str__", [](const std::vector<int>& v) {
+            std::ostringstream os;
+            os << "[";
+            for(size_t i = 0; i < v.size(); i++) {
+                if(i > 0) os << ", ";
+                os << v[i];
+            }
+            os << "]";
+            return os.str();
+        });
+
+    py::exec(R"(
+v = vector()
+v.push_back(1)
+v.push_back(2)
+v.push_back(3)
+print(v)
+assert v[0] == 1
+assert v[1] == 2
+assert v[2] == 3
+v[1] = 4
+assert v[1] == 4
+)");
+}

+ 3 - 2
include/pybind11/tests/stl.cpp

@@ -1,5 +1,5 @@
 #include "test.h"
-#include <pybind11/stl.h>
+#include "pybind11/stl.h"
 
 namespace {
 
@@ -119,7 +119,8 @@ TEST_F(PYBIND11_TEST, dict_like) {
         py::object obj = py::cast(m);
         EXPECT_EVAL_EQ("{'a': Point(1, 2), 'b': Point(3, 4)}", obj);
 
-        std::unordered_map<std::string, Point> m2 = obj.cast<std::unordered_map<std::string, Point>>();
+        std::unordered_map<std::string, Point> m2 =
+            obj.cast<std::unordered_map<std::string, Point>>();
         EXPECT_EQ(m, m2);
     }
 }