Support pointers to member functions in def_buffer.

Closes #857, by adding overloads to def_buffer that match pointers to
member functions and wrap them in lambdas.
This commit is contained in:
Bruce Merry 2017-05-17 10:52:33 +02:00 committed by Jason Rhinelander
parent 37b2383a64
commit fe0cf8b73b
3 changed files with 64 additions and 1 deletions

View File

@ -1020,6 +1020,16 @@ public:
return *this;
}
template <typename Return, typename Class, typename... Args>
class_ &def_buffer(Return (Class::*func)(Args...)) {
return def_buffer([func] (type &obj) { return (obj.*func)(); });
}
template <typename Return, typename Class, typename... Args>
class_ &def_buffer(Return (Class::*func)(Args...) const) {
return def_buffer([func] (const type &obj) { return (obj.*func)(); });
}
template <typename C, typename D, typename... Extra>
class_ &def_readwrite(const char *name, D C::*pm, const Extra&... extra) {
cpp_function fget([pm](const C &c) -> const D &{ return c.*pm; }, is_method(*this)),

View File

@ -74,6 +74,32 @@ private:
float *m_data;
};
struct PTMFBuffer {
int32_t value = 0;
py::buffer_info get_buffer_info() {
return py::buffer_info(&value, sizeof(value),
py::format_descriptor<int32_t>::format(), 1);
}
};
class ConstPTMFBuffer {
std::unique_ptr<int32_t> value;
public:
int32_t get_value() const { return *value; }
void set_value(int32_t v) { *value = v; }
py::buffer_info get_buffer_info() const {
return py::buffer_info(value.get(), sizeof(*value),
py::format_descriptor<int32_t>::format(), 1);
}
ConstPTMFBuffer() : value(new int32_t{0}) { };
};
struct DerivedPTMFBuffer : public PTMFBuffer { };
test_initializer buffers([](py::module &m) {
py::class_<Matrix> mtx(m, "Matrix", py::buffer_protocol());
@ -114,4 +140,21 @@ test_initializer buffers([](py::module &m) {
);
})
;
py::class_<PTMFBuffer>(m, "PTMFBuffer", py::buffer_protocol())
.def(py::init<>())
.def_readwrite("value", &PTMFBuffer::value)
.def_buffer(&PTMFBuffer::get_buffer_info);
py::class_<ConstPTMFBuffer>(m, "ConstPTMFBuffer", py::buffer_protocol())
.def(py::init<>())
.def_property("value", &ConstPTMFBuffer::get_value, &ConstPTMFBuffer::set_value)
.def_buffer(&ConstPTMFBuffer::get_buffer_info);
// Tests that passing a pointer to member to the base class works in
// the derived class.
py::class_<DerivedPTMFBuffer>(m, "DerivedPTMFBuffer", py::buffer_protocol())
.def(py::init<>())
.def_readwrite("value", (int32_t DerivedPTMFBuffer::*) &DerivedPTMFBuffer::value)
.def_buffer(&DerivedPTMFBuffer::get_buffer_info);
});

View File

@ -1,5 +1,6 @@
import struct
import pytest
from pybind11_tests import Matrix, ConstructorStats
from pybind11_tests import Matrix, ConstructorStats, PTMFBuffer, ConstPTMFBuffer, DerivedPTMFBuffer
pytestmark = pytest.requires_numpy
@ -60,3 +61,12 @@ def test_to_python():
# assert cstats.move_constructions >= 0 # Don't invoke any
assert cstats.copy_assignments == 0
assert cstats.move_assignments == 0
@pytest.unsupported_on_pypy
def test_ptmf():
for cls in [PTMFBuffer, ConstPTMFBuffer, DerivedPTMFBuffer]:
buf = cls()
buf.value = 0x12345678
value = struct.unpack('i', bytearray(buf))[0]
assert value == 0x12345678