allow nullptr string values (closes #138)

This commit is contained in:
Wenzel Jakob 2016-03-26 23:37:51 +01:00
parent 7393343f69
commit 9883ec01d7
4 changed files with 31 additions and 9 deletions

View File

@ -29,4 +29,6 @@ void init_ex14(py::module &m) {
m.def("return_void_ptr", []() { return (void *) 1234; }); 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("print_void_ptr", [](void *ptr) { std::cout << "Got void ptr : " << (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; });
} }

View File

@ -4,6 +4,8 @@ import sys
sys.path.append('.') sys.path.append('.')
from example import StringList, print_opaque_list from example import StringList, print_opaque_list
from example import return_void_ptr, print_void_ptr
from example import return_null_str, print_null_str
l = StringList() l = StringList()
l.push_back("Element 1") l.push_back("Element 1")
@ -13,6 +15,7 @@ print("Back element is %s" % l.back())
l.pop_back() l.pop_back()
print_opaque_list(l) print_opaque_list(l)
from example import return_void_ptr, print_void_ptr
print_void_ptr(return_void_ptr()) print_void_ptr(return_void_ptr())
print(return_null_str())
print_null_str(return_null_str())

View File

@ -5,3 +5,5 @@ Back element is Element 2
Opaque list: Opaque list:
Element 1 Element 1
Got void ptr : 1234 Got void ptr : 1234
None
Got null str : 0

View File

@ -391,6 +391,7 @@ public:
int err = PYBIND11_BYTES_AS_STRING_AND_SIZE(load_src.ptr(), &buffer, &length); int err = PYBIND11_BYTES_AS_STRING_AND_SIZE(load_src.ptr(), &buffer, &length);
if (err == -1) { PyErr_Clear(); return false; } // TypeError if (err == -1) { PyErr_Clear(); return false; } // TypeError
value = std::string(buffer, length); value = std::string(buffer, length);
success = true;
return true; return true;
} }
@ -399,6 +400,8 @@ public:
} }
PYBIND11_TYPE_CASTER(std::string, _(PYBIND11_STRING_NAME)); PYBIND11_TYPE_CASTER(std::string, _(PYBIND11_STRING_NAME));
protected:
bool success = false;
}; };
template <> class type_caster<std::wstring> { template <> class type_caster<std::wstring> {
@ -428,6 +431,7 @@ public:
#endif #endif
if (!buffer) { PyErr_Clear(); return false; } if (!buffer) { PyErr_Clear(); return false; }
value = std::wstring(buffer, length); value = std::wstring(buffer, length);
success = true;
return true; return true;
} }
@ -436,11 +440,19 @@ public:
} }
PYBIND11_TYPE_CASTER(std::wstring, _(PYBIND11_STRING_NAME)); PYBIND11_TYPE_CASTER(std::wstring, _(PYBIND11_STRING_NAME));
protected:
bool success = false;
}; };
template <> class type_caster<char> : public type_caster<std::string> { template <> class type_caster<char> : public type_caster<std::string> {
public: public:
bool load(handle src, bool convert) {
if (src.ptr() == Py_None) { return true; }
return type_caster<std::string>::load(src, convert);
}
static handle cast(const char *src, return_value_policy /* policy */, handle /* parent */) { static handle cast(const char *src, return_value_policy /* policy */, handle /* parent */) {
if (src == nullptr) return handle(Py_None).inc_ref();
return PyUnicode_FromString(src); return PyUnicode_FromString(src);
} }
@ -449,18 +461,21 @@ public:
return PyUnicode_DecodeLatin1(str, 1, nullptr); return PyUnicode_DecodeLatin1(str, 1, nullptr);
} }
operator char*() { return (char *) value.c_str(); } operator char*() { return success ? (char *) value.c_str() : nullptr; }
operator char() { if (value.length() > 0) return value[0]; else return '\0'; } operator char&() { return value[0]; }
template <typename T>
using cast_op_type = typename std::conditional<std::is_pointer<T>::value, char*, char>::type;
static PYBIND11_DESCR name() { return type_descr(_(PYBIND11_STRING_NAME)); } static PYBIND11_DESCR name() { return type_descr(_(PYBIND11_STRING_NAME)); }
}; };
template <> class type_caster<wchar_t> : public type_caster<std::wstring> { template <> class type_caster<wchar_t> : public type_caster<std::wstring> {
public: public:
bool load(handle src, bool convert) {
if (src.ptr() == Py_None) { return true; }
return type_caster<std::wstring>::load(src, convert);
}
static handle cast(const wchar_t *src, return_value_policy /* policy */, handle /* parent */) { static handle cast(const wchar_t *src, return_value_policy /* policy */, handle /* parent */) {
if (src == nullptr) return handle(Py_None).inc_ref();
return PyUnicode_FromWideChar(src, wcslen(src)); return PyUnicode_FromWideChar(src, wcslen(src));
} }
@ -469,8 +484,8 @@ public:
return PyUnicode_FromWideChar(wstr, 1); return PyUnicode_FromWideChar(wstr, 1);
} }
operator wchar_t*() { return (wchar_t *)value.c_str(); } operator wchar_t*() { return success ? (wchar_t *) value.c_str() : nullptr; }
operator wchar_t() { if (value.length() > 0) return value[0]; else return L'\0'; } operator wchar_t&() { return value[0]; }
static PYBIND11_DESCR name() { return type_descr(_(PYBIND11_STRING_NAME)); } static PYBIND11_DESCR name() { return type_descr(_(PYBIND11_STRING_NAME)); }
}; };