diff --git a/include/pybind11/common.h b/include/pybind11/common.h index 9db37adc8..eff105cfc 100644 --- a/include/pybind11/common.h +++ b/include/pybind11/common.h @@ -333,14 +333,14 @@ PYBIND11_RUNTIME_EXCEPTION(reference_cast_error) /// Used internally /// Format strings for basic number types #define PYBIND11_DECL_FMT(t, v) template<> struct format_descriptor \ { static constexpr const char* value = v; /* for backwards compatibility */ \ - static constexpr const char* format() { return value; } } + static std::string format() { return value; } } template struct format_descriptor { }; template struct format_descriptor::value>::type> { static constexpr const char value[2] = { "bBhHiIqQ"[detail::log2(sizeof(T))*2 + (std::is_unsigned::value ? 1 : 0)], '\0' }; - static constexpr const char* format() { return value; } + static std::string format() { return value; } }; template constexpr const char format_descriptor< diff --git a/include/pybind11/numpy.h b/include/pybind11/numpy.h index c71d9bbca..8653fc195 100644 --- a/include/pybind11/numpy.h +++ b/include/pybind11/numpy.h @@ -17,6 +17,7 @@ #include #include #include +#include #include #if defined(_MSC_VER) @@ -303,14 +304,14 @@ public: template struct format_descriptor::value>::type> { - static const char *format() { return detail::npy_format_descriptor::format(); } + static std::string format() { return detail::npy_format_descriptor::format(); } }; template struct format_descriptor { - static const char *format() { PYBIND11_DESCR s = detail::_() + detail::_("s"); return s.text(); } + static std::string format() { return std::to_string(N) + "s"; } }; template struct format_descriptor> { - static const char *format() { PYBIND11_DESCR s = detail::_() + detail::_("s"); return s.text(); } + static std::string format() { return std::to_string(N) + "s"; } }; NAMESPACE_BEGIN(detail) @@ -367,11 +368,7 @@ DECL_FMT(std::complex, NPY_CDOUBLE_, "complex128"); #define DECL_CHAR_FMT \ static PYBIND11_DESCR name() { return _("S") + _(); } \ - static pybind11::dtype dtype() { \ - PYBIND11_DESCR fmt = _("S") + _(); \ - return pybind11::dtype(fmt.text()); \ - } \ - static const char *format() { PYBIND11_DESCR s = _() + _("s"); return s.text(); } + static pybind11::dtype dtype() { return std::string("S") + std::to_string(N); } template struct npy_format_descriptor { DECL_CHAR_FMT }; template struct npy_format_descriptor> { DECL_CHAR_FMT }; #undef DECL_CHAR_FMT @@ -380,7 +377,7 @@ struct field_descriptor { const char *name; size_t offset; size_t size; - const char *format; + std::string format; dtype descr; }; @@ -389,15 +386,15 @@ struct npy_format_descriptor::value> static PYBIND11_DESCR name() { return _("struct"); } static pybind11::dtype dtype() { - if (!dtype_()) + if (!dtype_ptr) pybind11_fail("NumPy: unsupported buffer format!"); - return object(dtype_(), true); + return object(dtype_ptr, true); } - static const char* format() { - if (!dtype_()) + static std::string format() { + if (!dtype_ptr) pybind11_fail("NumPy: unsupported buffer format!"); - return format_().c_str(); + return format_str; } static void register_dtype(std::initializer_list fields) { @@ -409,7 +406,7 @@ struct npy_format_descriptor::value> formats.append(field.descr); offsets.append(int_(field.offset)); } - dtype_() = pybind11::dtype(names, formats, offsets, sizeof(T)).release().ptr(); + dtype_ptr = pybind11::dtype(names, formats, offsets, sizeof(T)).release().ptr(); // There is an existing bug in NumPy (as of v1.11): trailing bytes are // not encoded explicitly into the format string. This will supposedly @@ -436,20 +433,25 @@ struct npy_format_descriptor::value> if (sizeof(T) > offset) oss << (sizeof(T) - offset) << 'x'; oss << '}'; - format_() = oss.str(); + format_str = oss.str(); // Sanity check: verify that NumPy properly parses our buffer format string auto& api = npy_api::get(); - auto arr = array(buffer_info(nullptr, sizeof(T), format(), 1, { 0 }, { sizeof(T) })); - if (!api.PyArray_EquivTypes_(dtype_(), arr.dtype().ptr())) + auto arr = array(buffer_info(nullptr, sizeof(T), format(), 1)); + if (!api.PyArray_EquivTypes_(dtype_ptr, arr.dtype().ptr())) pybind11_fail("NumPy: invalid buffer descriptor!"); } private: - static inline PyObject*& dtype_() { static PyObject *ptr = nullptr; return ptr; } - static inline std::string& format_() { static std::string s; return s; } + static std::string format_str; + static PyObject* dtype_ptr; }; +template +std::string npy_format_descriptor::value>::type>::format_str; +template +PyObject* npy_format_descriptor::value>::type>::dtype_ptr = nullptr; + // Extract name, offset and format descriptor for a struct field #define PYBIND11_FIELD_DESCRIPTOR(Type, Field) \ ::pybind11::detail::field_descriptor { \