@@ -462,8 +462,15 @@ template <typename type> class type_caster<std::reference_wrapper<type>> : publi
462
462
template <typename _T> using cast_op_type = pybind11::detail::cast_op_type<_T>
463
463
464
464
465
+ template <typename CharT> using is_std_char_type = any_of<
466
+ std::is_same<CharT, char >, /* std::string */
467
+ std::is_same<CharT, char16_t >, /* std::u16string */
468
+ std::is_same<CharT, char32_t >, /* std::u32string */
469
+ std::is_same<CharT, wchar_t > /* std::wstring */
470
+ >;
471
+
465
472
template <typename T>
466
- struct type_caster <T, enable_if_t <std::is_arithmetic<T>::value>> {
473
+ struct type_caster <T, enable_if_t <std::is_arithmetic<T>::value && !is_std_char_type<T>::value >> {
467
474
typedef typename std::conditional<sizeof (T) <= sizeof (long ), long , long long >::type _py_type_0;
468
475
typedef typename std::conditional<std::is_signed<T>::value, _py_type_0, typename std::make_unsigned<_py_type_0>::type>::type _py_type_1;
469
476
typedef typename std::conditional<std::is_floating_point<T>::value, double , _py_type_1>::type py_type;
@@ -604,49 +611,22 @@ template <> class type_caster<bool> {
604
611
PYBIND11_TYPE_CASTER (bool , _(" bool" ));
605
612
};
606
613
607
- template <> class type_caster <std::string> {
608
- public:
609
- bool load (handle src, bool ) {
610
- object temp;
611
- handle load_src = src;
612
- if (!src) {
613
- return false ;
614
- } else if (PyUnicode_Check (load_src.ptr ())) {
615
- temp = reinterpret_steal<object>(PyUnicode_AsUTF8String (load_src.ptr ()));
616
- if (!temp) { PyErr_Clear (); return false ; } // UnicodeEncodeError
617
- load_src = temp;
618
- }
619
- char *buffer;
620
- ssize_t length;
621
- int err = PYBIND11_BYTES_AS_STRING_AND_SIZE (load_src.ptr (), &buffer, &length);
622
- if (err == -1 ) { PyErr_Clear (); return false ; } // TypeError
623
- value = std::string (buffer, (size_t ) length);
624
- success = true ;
625
- return true ;
626
- }
614
+ // Helper class for UTF-{8,16,32} strings:
615
+ template <typename CharT, class Traits , class Allocator >
616
+ struct type_caster <std::basic_string<CharT, Traits, Allocator>, enable_if_t <is_std_char_type<CharT>::value>> {
617
+ static constexpr unsigned int UTF_N =
618
+ std::is_same<CharT, char >::value ? 8 :
619
+ std::is_same<CharT, char16_t >::value ? 16 :
620
+ std::is_same<CharT, char32_t >::value ? 32 :
621
+ (sizeof (CharT) == 2 ? 16 : 32 ); /* std::wstring is UTF-16 on Windows, UTF-32 everywhere else */
627
622
628
- static handle cast (const std::string &src, return_value_policy /* policy */ , handle /* parent */ ) {
629
- return PyUnicode_FromStringAndSize (src.c_str (), (ssize_t ) src.length ());
630
- }
623
+ // C++ only requires char/char16_t/char32_t to be at least 8/16/32 bits, but Python's encoding
624
+ // assumes exactly 1/2/4 bytes:
625
+ static_assert (sizeof (CharT) == UTF_N / 8 ,
626
+ " Internal error: string type_caster requires 1/2/4-sized character types" );
631
627
632
- PYBIND11_TYPE_CASTER (std::string, _(PYBIND11_STRING_NAME));
633
- protected:
634
- bool success = false ;
635
- };
628
+ using StringType = std::basic_string<CharT, Traits, Allocator>;
636
629
637
- template <typename type, typename deleter> class type_caster <std::unique_ptr<type, deleter>> {
638
- public:
639
- static handle cast (std::unique_ptr<type, deleter> &&src, return_value_policy policy, handle parent) {
640
- handle result = type_caster_base<type>::cast (src.get (), policy, parent);
641
- if (result)
642
- src.release ();
643
- return result;
644
- }
645
- static PYBIND11_DESCR name () { return type_caster_base<type>::name (); }
646
- };
647
-
648
- template <> class type_caster <std::wstring> {
649
- public:
650
630
bool load (handle src, bool ) {
651
631
object temp;
652
632
handle load_src = src;
@@ -657,78 +637,62 @@ template <> class type_caster<std::wstring> {
657
637
if (!temp) { PyErr_Clear (); return false ; }
658
638
load_src = temp;
659
639
}
660
- wchar_t *buffer = nullptr ;
661
- ssize_t length = -1 ;
662
- #if PY_MAJOR_VERSION >= 3
663
- buffer = PyUnicode_AsWideCharString (load_src.ptr (), &length);
664
- #else
665
- temp = reinterpret_steal<object>(PyUnicode_AsEncodedString (
666
- load_src.ptr (), sizeof (wchar_t ) == sizeof (short )
667
- ? " utf16" : " utf32" , nullptr ));
668
-
669
- if (temp) {
670
- int err = PYBIND11_BYTES_AS_STRING_AND_SIZE (temp.ptr (), (char **) &buffer, &length);
671
- if (err == -1 ) { buffer = nullptr ; } // TypeError
672
- length = length / (ssize_t ) sizeof (wchar_t ) - 1 ; ++buffer; // Skip BOM
673
- }
674
- #endif
675
- if (!buffer) { PyErr_Clear (); return false ; }
676
- value = std::wstring (buffer, (size_t ) length);
640
+
641
+ object utfNbytes = reinterpret_steal<object>(PyUnicode_AsEncodedString (
642
+ load_src.ptr (),
643
+ UTF_N == 8 ? " utf8" : UTF_N == 16 ? " utf16" : " utf32" ,
644
+ nullptr ));
645
+ if (!utfNbytes) { PyErr_Clear (); return false ; }
646
+
647
+ const CharT *buffer = reinterpret_cast <const CharT *>(PYBIND11_BYTES_AS_STRING (utfNbytes.ptr ()));
648
+ size_t length = (size_t ) PYBIND11_BYTES_SIZE (utfNbytes.ptr ()) / sizeof (CharT);
649
+ if (UTF_N > 8 ) { buffer++; length--; } // Skip BOM for UTF-16/32
650
+ value = StringType (buffer, length);
677
651
success = true ;
678
652
return true ;
679
653
}
680
654
681
- static handle cast (const std::wstring &src, return_value_policy /* policy */ , handle /* parent */ ) {
682
- return PyUnicode_FromWideChar (src.c_str (), (ssize_t ) src.length ());
655
+ static handle cast (const StringType &src, return_value_policy /* policy */ , handle /* parent */ ) {
656
+ const char *buffer = reinterpret_cast <const char *>(src.c_str ());
657
+ ssize_t nbytes = ssize_t (src.size () * sizeof (CharT));
658
+ handle s = PyUnicode_Decode (buffer, nbytes, UTF_N == 8 ? " utf8" : UTF_N == 16 ? " utf16" : " utf32" , nullptr );
659
+ if (!s) throw error_already_set ();
660
+ return s;
683
661
}
684
662
685
- PYBIND11_TYPE_CASTER (std::wstring , _(PYBIND11_STRING_NAME));
663
+ PYBIND11_TYPE_CASTER (StringType , _(PYBIND11_STRING_NAME));
686
664
protected:
687
665
bool success = false ;
688
666
};
689
667
690
- template <> class type_caster <char > : public type_caster<std::string> {
668
+ template <typename CharT> struct type_caster <CharT, enable_if_t <is_std_char_type<CharT>::value>>
669
+ : type_caster<std::basic_string<CharT>> {
670
+ using StringType = std::basic_string<CharT>;
671
+ using StringCaster = type_caster<StringType>;
672
+ using StringCaster::success;
673
+ using StringCaster::value;
691
674
public:
692
675
bool load (handle src, bool convert) {
693
676
if (src.is_none ()) return true ;
694
- return type_caster<std::string> ::load (src, convert);
677
+ return StringCaster ::load (src, convert);
695
678
}
696
679
697
- static handle cast (const char *src, return_value_policy /* policy */ , handle /* parent */ ) {
680
+ static handle cast (const CharT *src, return_value_policy policy, handle parent) {
698
681
if (src == nullptr ) return none ().inc_ref ();
699
- return PyUnicode_FromString (src);
700
- }
701
-
702
- static handle cast (char src, return_value_policy /* policy */ , handle /* parent */ ) {
703
- char str[2 ] = { src, ' \0 ' };
704
- return PyUnicode_DecodeLatin1 (str, 1 , nullptr );
705
- }
706
-
707
- operator char *() { return success ? (char *) value.c_str () : nullptr ; }
708
- operator char &() { return value[0 ]; }
709
-
710
- static PYBIND11_DESCR name () { return type_descr (_ (PYBIND11_STRING_NAME)); }
711
- };
712
-
713
- template <> class type_caster <wchar_t > : public type_caster<std::wstring> {
714
- public:
715
- bool load (handle src, bool convert) {
716
- if (src.is_none ()) return true ;
717
- return type_caster<std::wstring>::load (src, convert);
682
+ return StringCaster::cast (StringType (src), policy, parent);
718
683
}
719
684
720
- static handle cast (const wchar_t *src, return_value_policy /* policy */ , handle /* parent */ ) {
721
- if (src == nullptr ) return none ().inc_ref ();
722
- return PyUnicode_FromWideChar (src, (ssize_t ) wcslen (src));
723
- }
724
-
725
- static handle cast (wchar_t src, return_value_policy /* policy */ , handle /* parent */ ) {
726
- wchar_t wstr[2 ] = { src, L' \0 ' };
727
- return PyUnicode_FromWideChar (wstr, 1 );
685
+ static handle cast (CharT src, return_value_policy policy, handle parent) {
686
+ if (std::is_same<char , CharT>::value) {
687
+ handle s = PyUnicode_DecodeLatin1 ((const char *) &src, 1 , nullptr );
688
+ if (!s) throw error_already_set ();
689
+ return s;
690
+ }
691
+ return StringCaster::cast (StringType (1 , src), policy, parent);
728
692
}
729
693
730
- operator wchar_t *() { return success ? (wchar_t *) value.c_str () : nullptr ; }
731
- operator wchar_t &() { return value[0 ]; }
694
+ operator CharT *() { return success ? (CharT *) value.c_str () : nullptr ; }
695
+ operator CharT &() { return value[0 ]; }
732
696
733
697
static PYBIND11_DESCR name () { return type_descr (_ (PYBIND11_STRING_NAME)); }
734
698
};
@@ -835,6 +799,17 @@ template <typename... Tuple> class type_caster<std::tuple<Tuple...>> {
835
799
std::tuple<make_caster<Tuple>...> value;
836
800
};
837
801
802
+ template <typename type, typename deleter> class type_caster <std::unique_ptr<type, deleter>> {
803
+ public:
804
+ static handle cast (std::unique_ptr<type, deleter> &&src, return_value_policy policy, handle parent) {
805
+ handle result = type_caster_base<type>::cast (src.get (), policy, parent);
806
+ if (result)
807
+ src.release ();
808
+ return result;
809
+ }
810
+ static PYBIND11_DESCR name () { return type_caster_base<type>::name (); }
811
+ };
812
+
838
813
// / Type caster for holder types like std::shared_ptr, etc.
839
814
template <typename type, typename holder_type> class type_caster_holder : public type_caster_base <type> {
840
815
public:
@@ -1231,12 +1206,11 @@ NAMESPACE_BEGIN(detail)
1231
1206
// forward declaration
1232
1207
struct function_record;
1233
1208
1234
- using function_arguments = const std::vector<handle> &;
1235
-
1236
1209
// / Helper class which loads arguments for C++ functions called from Python
1237
1210
template <typename ... Args>
1238
1211
class argument_loader {
1239
1212
using indices = make_index_sequence<sizeof ...(Args)>;
1213
+ using function_arguments = const std::vector<handle> &;
1240
1214
1241
1215
template <typename Arg> using argument_is_args = std::is_same<intrinsic_t <Arg>, args>;
1242
1216
template <typename Arg> using argument_is_kwargs = std::is_same<intrinsic_t <Arg>, kwargs>;
0 commit comments