From 1083c2b9c721cd7e6a93219c2cd704b108a3f86a Mon Sep 17 00:00:00 2001 From: Guillaume Giraud Date: Tue, 25 May 2021 21:28:38 -0500 Subject: [PATCH 1/7] added support for std::basic_string_view binding by adding uint8_t in the set of types validated by is_std_char_type --- include/pybind11/cast.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/pybind11/cast.h b/include/pybind11/cast.h index f68a35bfa..1d6aaecda 100644 --- a/include/pybind11/cast.h +++ b/include/pybind11/cast.h @@ -107,6 +107,7 @@ public: template using is_std_char_type = any_of< std::is_same, /* std::string */ + std::is_same, /* std::basic_string and std::basic_string_view */ #if defined(PYBIND11_HAS_U8STRING) std::is_same, /* std::u8string */ #endif From c50af5b8f8a21d59c66b4a2e118f93cbd5f2b5e2 Mon Sep 17 00:00:00 2001 From: Guillaume Giraud Date: Wed, 26 May 2021 10:45:10 -0500 Subject: [PATCH 2/7] add support in string_caster for loading bytes 'as-is' into uint8_t-based strings and string_views --- include/pybind11/cast.h | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/include/pybind11/cast.h b/include/pybind11/cast.h index 1d6aaecda..e127c31fb 100644 --- a/include/pybind11/cast.h +++ b/include/pybind11/cast.h @@ -389,9 +389,13 @@ template struct string_caster { static handle cast(const StringType &src, return_value_policy /* policy */, handle /* parent */) { const char *buffer = reinterpret_cast(src.data()); auto nbytes = ssize_t(src.size() * sizeof(CharT)); - handle s = decode_utfN(buffer, nbytes); - if (!s) throw error_already_set(); - return s; + if (std::is_same_v) + return PyBytes_FromStringAndSize(buffer, nbytes); + else { + handle s = decode_utfN(buffer, nbytes); + if (!s) throw error_already_set(); + return s; + } } PYBIND11_TYPE_CASTER(StringType, _(PYBIND11_STRING_NAME)); @@ -409,18 +413,20 @@ private: return PyUnicode_Decode(buffer, nbytes, UTF_N == 8 ? "utf-8" : UTF_N == 16 ? "utf-16" : "utf-32", nullptr); #endif } - + template + using accept_bytes_as_is = any_of, std::is_same>; + // When loading into a std::string or char*, accept a bytes object as-is (i.e. // without any encoding/decoding attempt). For other C++ char sizes this is a no-op. // which supports loading a unicode from a str, doesn't take this path. template - bool load_bytes(enable_if_t::value, handle> src) { + bool load_bytes(enable_if_t::value, handle> src) { if (PYBIND11_BYTES_CHECK(src.ptr())) { // We were passed a Python 3 raw bytes; accept it into a std::string or char* // without any encoding attempt. const char *bytes = PYBIND11_BYTES_AS_STRING(src.ptr()); if (bytes) { - value = StringType(bytes, (size_t) PYBIND11_BYTES_SIZE(src.ptr())); + value = StringType((const C *) bytes, (size_t) PYBIND11_BYTES_SIZE(src.ptr())); return true; } } @@ -429,7 +435,9 @@ private: } template - bool load_bytes(enable_if_t::value, handle>) { return false; } + bool load_bytes(enable_if_t::value, handle>) { + return false; + } }; template From 263ff1aeb741f946c78b944fc00ebc368396c0a0 Mon Sep 17 00:00:00 2001 From: Guillaume Giraud Date: Wed, 16 Mar 2022 15:39:56 +0100 Subject: [PATCH 3/7] add support for std::basic_string/std::basic_string_view and by extending string_caster coverage to those types. Treat strings of those types as raw bytes (no decoding) --- include/pybind11/cast.h | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/include/pybind11/cast.h b/include/pybind11/cast.h index d45b49c52..df6950cef 100644 --- a/include/pybind11/cast.h +++ b/include/pybind11/cast.h @@ -108,6 +108,10 @@ public: template using is_std_char_type = any_of, /* std::string */ +#if defined(PYBIND11_CPP17) + std::is_same, /* std::byte */ +#endif + std::is_same, /* uint8_t */ #if defined(PYBIND11_HAS_U8STRING) std::is_same, /* std::u8string */ #endif @@ -434,11 +438,19 @@ struct string_caster { cast(const StringType &src, return_value_policy /* policy */, handle /* parent */) { const char *buffer = reinterpret_cast(src.data()); auto nbytes = ssize_t(src.size() * sizeof(CharT)); - handle s = decode_utfN(buffer, nbytes); - if (!s) { - throw error_already_set(); + if (std::is_same_v +#if defined(PYBIND11_CPP17) + or std::is_same_v +#endif + ) { + return PyBytes_FromStringAndSize(buffer, nbytes); + } else { + handle s = decode_utfN(buffer, nbytes); + if (!s) { + throw error_already_set(); + } + return s; } - return s; } PYBIND11_TYPE_CASTER(StringType, const_name(PYBIND11_STRING_NAME)); @@ -461,12 +473,18 @@ private: nullptr); #endif } + template + using accept_bytes_as_is = any_of, +#if defined(PYBIND11_CPP17) + std::is_same, +#endif + std::is_same>; // When loading into a std::string or char*, accept a bytes/bytearray object as-is (i.e. // without any encoding/decoding attempt). For other C++ char sizes this is a no-op. // which supports loading a unicode from a str, doesn't take this path. template - bool load_raw(enable_if_t::value, handle> src) { + bool load_raw(enable_if_t::value, handle> src) { if (PYBIND11_BYTES_CHECK(src.ptr())) { // We were passed raw bytes; accept it into a std::string or char* // without any encoding attempt. @@ -474,7 +492,7 @@ private: if (!bytes) { pybind11_fail("Unexpected PYBIND11_BYTES_AS_STRING() failure."); } - value = StringType(bytes, (size_t) PYBIND11_BYTES_SIZE(src.ptr())); + value = StringType((const C *) bytes, (size_t) PYBIND11_BYTES_SIZE(src.ptr())); return true; } if (PyByteArray_Check(src.ptr())) { @@ -492,7 +510,7 @@ private: } template - bool load_raw(enable_if_t::value, handle>) { + bool load_raw(enable_if_t::value, handle>) { return false; } }; From a453fdb2b13d42aba2359eba3a2678a5ceada036 Mon Sep 17 00:00:00 2001 From: Guillaume Giraud Date: Wed, 16 Mar 2022 16:12:01 +0100 Subject: [PATCH 4/7] Added missing c-style cast in string_caster::load_raw for the bytearray case --- include/pybind11/cast.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/pybind11/cast.h b/include/pybind11/cast.h index df6950cef..b08d27a84 100644 --- a/include/pybind11/cast.h +++ b/include/pybind11/cast.h @@ -502,7 +502,7 @@ private: if (!bytearray) { pybind11_fail("Unexpected PyByteArray_AsString() failure."); } - value = StringType(bytearray, (size_t) PyByteArray_Size(src.ptr())); + value = StringType((const C *) bytearray, (size_t) PyByteArray_Size(src.ptr())); return true; } From 9fb90cb30c6441661b040b3f147cea6724d40817 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 16 Mar 2022 15:16:41 +0000 Subject: [PATCH 5/7] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- include/pybind11/cast.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/pybind11/cast.h b/include/pybind11/cast.h index b08d27a84..fb492111a 100644 --- a/include/pybind11/cast.h +++ b/include/pybind11/cast.h @@ -473,7 +473,7 @@ private: nullptr); #endif } - template + template using accept_bytes_as_is = any_of, #if defined(PYBIND11_CPP17) std::is_same, From 19d8f06c52dd2c4f8568808172b5afde9c7881ec Mon Sep 17 00:00:00 2001 From: Guillaume Giraud Date: Wed, 16 Mar 2022 16:31:01 +0100 Subject: [PATCH 6/7] use std::is_same<...>::value instead of std::is_same_v<...> for c++11 compliance --- include/pybind11/cast.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/pybind11/cast.h b/include/pybind11/cast.h index fb492111a..14cad1889 100644 --- a/include/pybind11/cast.h +++ b/include/pybind11/cast.h @@ -438,9 +438,9 @@ struct string_caster { cast(const StringType &src, return_value_policy /* policy */, handle /* parent */) { const char *buffer = reinterpret_cast(src.data()); auto nbytes = ssize_t(src.size() * sizeof(CharT)); - if (std::is_same_v + if (std::is_same::value #if defined(PYBIND11_CPP17) - or std::is_same_v + || std::is_same::value #endif ) { return PyBytes_FromStringAndSize(buffer, nbytes); From 1334c7eae78d89439612e09c27466a14db840d74 Mon Sep 17 00:00:00 2001 From: Guillaume Giraud Date: Sat, 2 Apr 2022 13:14:41 +0200 Subject: [PATCH 7/7] use if constexpr under PYBIND11_CPP17 to fix compilation warning --- include/pybind11/cast.h | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/include/pybind11/cast.h b/include/pybind11/cast.h index 14cad1889..8879f2e5e 100644 --- a/include/pybind11/cast.h +++ b/include/pybind11/cast.h @@ -438,11 +438,13 @@ struct string_caster { cast(const StringType &src, return_value_policy /* policy */, handle /* parent */) { const char *buffer = reinterpret_cast(src.data()); auto nbytes = ssize_t(src.size() * sizeof(CharT)); - if (std::is_same::value #if defined(PYBIND11_CPP17) - || std::is_same::value + if constexpr (std::is_same::value || + std::is_same::value) +#else + if (std::is_same::value) #endif - ) { + { return PyBytes_FromStringAndSize(buffer, nbytes); } else { handle s = decode_utfN(buffer, nbytes);