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; std::cout << "]" << std::endl;
}); });
m.def("return_void_ptr", []() { return (void *) 1234; }); m.def("return_void_ptr", []() { return (void *) 0x1234; });
m.def("print_void_ptr", [](void *ptr) { std::cout << "Got void ptr : " << (uint64_t) ptr << std::endl; }); 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("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> { m.def("return_unique_ptr", []() -> std::unique_ptr<StringList> {
StringList *result = new StringList(); StringList *result = new StringList();

View File

@ -33,7 +33,12 @@ print_opaque_list(cvp.stringList)
##### #####
print_void_ptr(return_void_ptr()) print_void_ptr(return_void_ptr())
print_void_ptr(Example1()) # Should also work for other C++ types 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(return_null_str())
print_null_str(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: [Element 1]
Opaque list: [] Opaque list: []
Opaque list: [Element 1, Element 3] 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 None
Got null str : 0 Got null str : 0x0
<example.StringList object at 0x104a47500> <example.StringList object at 0x10d3277a0>
Opaque list: [some value] Opaque list: [some value]

View File

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

View File

@ -450,7 +450,7 @@ protected:
return nullptr; return nullptr;
} else { } else {
if (overloads->is_constructor) { 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. */ holder type (e.g. std::unique_ptr) must still be initialized. */
PyObject *inst = PyTuple_GetItem(args, 0); PyObject *inst = PyTuple_GetItem(args, 0);
auto tinfo = detail::get_type_info(Py_TYPE(inst)); auto tinfo = detail::get_type_info(Py_TYPE(inst));