enable passing C++ instances to void*-valued arguments

This commit is contained in:
Wenzel Jakob 2016-04-30 19:56:10 +02:00
parent e8b9dd263c
commit 772c6d54d6
5 changed files with 40 additions and 15 deletions

View File

@ -49,10 +49,10 @@ void init_ex14(py::module &m) {
std::cout << "]" << std::endl;
});
m.def("return_void_ptr", []() { return (void *) 1234; });
m.def("print_void_ptr", [](void *ptr) { std::cout << "Got void ptr : " << (uint64_t) ptr << std::endl; });
m.def("return_void_ptr", []() { return (void *) 0x1234; });
m.def("print_void_ptr", [](void *ptr) { std::cout << "Got void ptr : 0x" << std::hex << (uint64_t) ptr << std::endl; });
m.def("return_null_str", []() { return (char *) nullptr; });
m.def("print_null_str", [](char *ptr) { std::cout << "Got null str : " << (uint64_t) ptr << std::endl; });
m.def("print_null_str", [](char *ptr) { std::cout << "Got null str : 0x" << std::hex << (uint64_t) ptr << std::endl; });
m.def("return_unique_ptr", []() -> std::unique_ptr<StringList> {
StringList *result = new StringList();

View File

@ -35,6 +35,11 @@ print_opaque_list(cvp.stringList)
print_void_ptr(return_void_ptr())
print_void_ptr(Example1()) # Should also work for other C++ types
try:
print_void_ptr([1, 2, 3]) # This should not work
except Exception as e:
print("Caught expected exception: " + str(e))
print(return_null_str())
print_null_str(return_null_str())

View File

@ -5,8 +5,14 @@ Back element is Element 2
Opaque list: [Element 1]
Opaque list: []
Opaque list: [Element 1, Element 3]
Got void ptr : 1234
Got void ptr : 0x1234
Called Example1 default constructor..
Got void ptr : 0x7f9ba0f3c430
Called Example1 destructor (0)
Caught expected exception: Incompatible function arguments. The following argument types are supported:
1. (capsule) -> NoneType
None
Got null str : 0
<example.StringList object at 0x104a47500>
Got null str : 0x0
<example.StringList object at 0x10d3277a0>
Opaque list: [some value]

View File

@ -52,15 +52,18 @@ PYBIND11_NOINLINE inline internals &get_internals() {
return *internals_ptr;
}
PYBIND11_NOINLINE inline detail::type_info* get_type_info(PyTypeObject *type) {
PYBIND11_NOINLINE inline detail::type_info* get_type_info(PyTypeObject *type, bool throw_if_missing = true) {
auto const &type_dict = get_internals().registered_types_py;
do {
auto it = type_dict.find(type);
if (it != type_dict.end())
return (detail::type_info *) it->second;
type = type->tp_base;
if (!type)
if (!type) {
if (throw_if_missing)
pybind11_fail("pybind11::detail::get_type_info: unable to find type object!");
return nullptr;
}
} while (true);
}
@ -382,13 +385,24 @@ public:
value = nullptr;
return true;
}
/* Check if this is a capsule */
capsule c(h, true);
if (!c.check())
return false;
if (c.check()) {
value = (void *) c;
return true;
}
/* Check if this is a C++ type */
if (get_type_info((PyTypeObject *) h.get_type().ptr(), false)) {
value = ((instance<void> *) h.ptr())->value;
return true;
}
/* Fail */
return false;
}
static handle cast(const void *ptr, return_value_policy /* policy */, handle /* parent */) {
if (ptr)
return capsule(ptr).release();

View File

@ -450,7 +450,7 @@ protected:
return nullptr;
} else {
if (overloads->is_constructor) {
/* When a construtor ran successfully, the corresponding
/* When a constructor ran successfully, the corresponding
holder type (e.g. std::unique_ptr) must still be initialized. */
PyObject *inst = PyTuple_GetItem(args, 0);
auto tinfo = detail::get_type_info(Py_TYPE(inst));