diff --git a/include/pybind11/pybind11.h b/include/pybind11/pybind11.h index 6655a213..f2036903 100644 --- a/include/pybind11/pybind11.h +++ b/include/pybind11/pybind11.h @@ -394,7 +394,7 @@ class cpp_function : public function { // it alive. auto *rec = unique_rec.get(); - // Note the "@__setstate__" manipulation below. + // Note the "__setstate__" manipulation below. rec->is_constructor = rec->name != nullptr && (std::strcmp(rec->name, "__init__") == 0 || std::strcmp(rec->name, "__setstate__") == 0); @@ -410,9 +410,9 @@ class cpp_function : public function { /* Create copies of all referenced C-style strings */ if (rec->name == nullptr) { rec->name = guarded_strdup(""); - } else if (std::strcmp(rec->name, "@__setstate__") == 0) { + } else if (std::strcmp(rec->name, "__setstate__[non-constructor]") == 0) { // See google/pywrapcc#30094 for background. - rec->name = guarded_strdup(rec->name + 1); + rec->name = guarded_strdup("__setstate__"); } else { rec->name = guarded_strdup(rec->name); } diff --git a/tests/test_pickling.cpp b/tests/test_pickling.cpp index 5b7a7a2b..fae2c115 100644 --- a/tests/test_pickling.cpp +++ b/tests/test_pickling.cpp @@ -65,10 +65,16 @@ void wrap(py::module m) { namespace exercise_getinitargs_getstate_setstate { -// Mechanism similar to what was established with Boost.Python: -// https://www.boost.org/doc/libs/1_58_0/libs/python/doc/v2/pickle.html +// Exercise `__setstate__[non-constructor]` (see google/pywrapcc#30094), which +// was added to support a pickle protocol as established with Boost.Python +// (in 2002): +// https://www.boost.org/doc/libs/1_31_0/libs/python/doc/v2/pickle.html // This mechanism was also adopted for PyCLIF: // https://github.com/google/clif/blob/7d388e1de7db5beeb3d7429c18a2776d8188f44f/clif/testing/python/pickle_compatibility.clif +// The code below exercises the pickle protocol intentionally exactly as used +// in PyCLIF, to ensure that pybind11 stays fully compatible with existing +// client code relying on the long-established protocol. (It is impractical to +// change all such client code.) class StoreTwoWithState { public: @@ -97,7 +103,7 @@ void wrap(py::module m) { }, py::arg("protocol") = -1) .def( - "@__setstate__", // See google/pywrapcc#30094 for background. + "__setstate__[non-constructor]", // See google/pywrapcc#30094 for background. [](StoreTwoWithState *self, const std::string &state) { self->SetState(state); }, py::arg("state")); }