Skip to content

Commit 089d35c

Browse files
committed
Fix ct_string type caster for updated pybind11
1 parent c81e450 commit 089d35c

File tree

1 file changed

+28
-12
lines changed

1 file changed

+28
-12
lines changed

subprojects/robotpy-wpiutil/wpiutil/src/type_casters/wpi_ct_string_type_caster.h

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@
88
namespace pybind11 {
99
namespace detail {
1010

11-
template <typename Char, typename Traits, size_t N>
12-
struct type_caster<wpi::ct_string<Char, Traits, N>> {
13-
using str_type = wpi::ct_string<Char, Traits, N>;
11+
template <typename CharT, typename Traits, size_t N>
12+
struct type_caster<wpi::ct_string<CharT, Traits, N>> {
13+
using str_type = wpi::ct_string<CharT, Traits, N>;
1414
PYBIND11_TYPE_CASTER(str_type, const_name(PYBIND11_STRING_NAME));
1515

1616
// TODO
@@ -21,19 +21,35 @@ struct type_caster<wpi::ct_string<Char, Traits, N>> {
2121
static handle cast(const str_type& src,
2222
py::return_value_policy policy,
2323
py::handle parent) {
24-
const char *buffer = reinterpret_cast<const char *>(src.data());
25-
auto nbytes = ssize_t(src.size() * sizeof(Char));
26-
handle s;
27-
if (policy == return_value_policy::_return_as_bytes) {
28-
s = PyBytes_FromStringAndSize(buffer, nbytes);
29-
} else {
30-
s = PyUnicode_DecodeUTF8(buffer, nbytes, nullptr);
31-
}
24+
const char *buffer = reinterpret_cast<const char *>(src.data());
25+
auto nbytes = ssize_t(src.size() * sizeof(CharT));
26+
handle s = decode_utfN(buffer, nbytes);
3227
if (!s) {
3328
throw error_already_set();
3429
}
3530
return s;
36-
}
31+
}
32+
33+
// copied from py::string_caster
34+
static constexpr size_t UTF_N = 8 * sizeof(CharT);
35+
36+
static handle decode_utfN(const char *buffer, ssize_t nbytes) {
37+
#if !defined(PYPY_VERSION)
38+
return UTF_N == 8 ? PyUnicode_DecodeUTF8(buffer, nbytes, nullptr)
39+
: UTF_N == 16 ? PyUnicode_DecodeUTF16(buffer, nbytes, nullptr, nullptr)
40+
: PyUnicode_DecodeUTF32(buffer, nbytes, nullptr, nullptr);
41+
#else
42+
// PyPy segfaults when on PyUnicode_DecodeUTF16 (and possibly on PyUnicode_DecodeUTF32 as
43+
// well), so bypass the whole thing by just passing the encoding as a string value, which
44+
// works properly:
45+
return PyUnicode_Decode(buffer,
46+
nbytes,
47+
UTF_N == 8 ? "utf-8"
48+
: UTF_N == 16 ? "utf-16"
49+
: "utf-32",
50+
nullptr);
51+
#endif
52+
}
3753

3854
};
3955

0 commit comments

Comments
 (0)