diff --git a/include/boost/python/detail/config.hpp b/include/boost/python/detail/config.hpp index 4e2b85ab..44d0e310 100644 --- a/include/boost/python/detail/config.hpp +++ b/include/boost/python/detail/config.hpp @@ -71,7 +71,7 @@ # define BOOST_PYTHON_NO_TEMPLATE_EXPORT #endif -#if defined(BOOST_PYTHON_DYNAMIC_LIB) && defined(_WIN32) +#if defined(BOOST_PYTHON_DYNAMIC_LIB) && defined(_WIN32) || defined(__CYGWIN__) # if defined(BOOST_PYTHON_SOURCE) # define BOOST_PYTHON_DECL __declspec(dllexport) # define BOOST_PYTHON_BUILD_DLL diff --git a/include/boost/python/scope.hpp b/include/boost/python/scope.hpp index f905858e..caaf3b1c 100644 --- a/include/boost/python/scope.hpp +++ b/include/boost/python/scope.hpp @@ -13,8 +13,15 @@ namespace boost { namespace python { -class BOOST_PYTHON_DECL scope - : public object +namespace detail +{ + // Making this a namespace-scope variable to avoid Cygwin issues. + // Use a PyObject* to avoid problems with static destruction after Py_Finalize + extern BOOST_PYTHON_DECL PyObject* current_scope; +} + +class scope + : public object { public: inline scope(scope const&); @@ -27,32 +34,27 @@ class BOOST_PYTHON_DECL scope private: // unimplemented functions void operator=(scope const&); - - private: // static members - - // Use a PyObject* to avoid problems with static destruction after Py_Finalize - static PyObject* current_scope; }; inline scope::scope(object const& new_scope) : object(new_scope) - , m_previous_scope(current_scope) + , m_previous_scope(detail::current_scope) { - current_scope = python::incref(new_scope.ptr()); + detail::current_scope = python::incref(new_scope.ptr()); } inline scope::scope() : object(detail::borrowed_reference( - current_scope ? current_scope : Py_None + detail::current_scope ? detail::current_scope : Py_None )) - , m_previous_scope(python::xincref(current_scope)) + , m_previous_scope(python::xincref(detail::current_scope)) { } inline scope::~scope() { - python::xdecref(current_scope); - current_scope = m_previous_scope; + python::xdecref(detail::current_scope); + detail::current_scope = m_previous_scope; } namespace converter @@ -67,9 +69,9 @@ namespace converter // Placing this after the specialization above suppresses a CWPro8.3 bug inline scope::scope(scope const& new_scope) : object(new_scope) - , m_previous_scope(current_scope) + , m_previous_scope(detail::current_scope) { - current_scope = python::incref(new_scope.ptr()); + detail::current_scope = python::incref(new_scope.ptr()); } }} // namespace boost::python diff --git a/include/boost/python/type_id.hpp b/include/boost/python/type_id.hpp index 88385582..908e0ac1 100755 --- a/include/boost/python/type_id.hpp +++ b/include/boost/python/type_id.hpp @@ -15,6 +15,13 @@ # include # include +# ifndef BOOST_PYTHON_HAVE_GCC_CP_DEMANGLE +# if defined(__GNUC__) \ + && ((__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 1))) +# define BOOST_PYTHON_HAVE_GCC_CP_DEMANGLE +# endif +# endif + namespace boost { namespace python { // for this compiler at least, cross-shared-library type_info @@ -87,7 +94,7 @@ BOOST_PYTHON_SIGNED_INTEGRAL_TYPE_ID(long long) # undef BOOST_PYTHON_SIGNED_INTEGRAL_TYPE_ID # endif - +// inline type_info::type_info(std::type_info const& id) : m_base_type( # ifdef BOOST_PYTHON_TYPE_ID_NAME @@ -117,12 +124,26 @@ inline bool type_info::operator==(type_info const& rhs) const # endif } +# ifdef BOOST_PYTHON_HAVE_GCC_CP_DEMANGLE +namespace detail +{ + BOOST_PYTHON_DECL char const* gcc_demangle(char const*); +} +# endif + inline char const* type_info::name() const { -# ifdef BOOST_PYTHON_TYPE_ID_NAME - return m_base_type; + char const* raw_name + = m_base_type +# ifndef BOOST_PYTHON_TYPE_ID_NAME + ->name() +# endif + ; + +# ifdef BOOST_PYTHON_HAVE_GCC_CP_DEMANGLE + return detail::gcc_demangle(raw_name); # else - return m_base_type->name(); + return raw_name; # endif } diff --git a/src/converter/from_python.cpp b/src/converter/from_python.cpp index f0667254..d12fb756 100644 --- a/src/converter/from_python.cpp +++ b/src/converter/from_python.cpp @@ -14,8 +14,6 @@ #include #include -#include - #include #include diff --git a/src/converter/registry.cpp b/src/converter/registry.cpp index 2b523cdc..3a90ff9a 100644 --- a/src/converter/registry.cpp +++ b/src/converter/registry.cpp @@ -7,8 +7,6 @@ #include #include -#include - #include #include @@ -25,7 +23,7 @@ BOOST_PYTHON_DECL PyTypeObject* registration::get_class_object() const ::PyErr_Format( PyExc_TypeError , const_cast("No Python class registered for C++ class %s") - , target_type.name()); + , this->target_type.name()); throw_error_already_set(); } @@ -40,7 +38,9 @@ BOOST_PYTHON_DECL PyObject* registration::to_python(void const volatile* source) handle<> msg( ::PyString_FromFormat( "No to_python (by-value) converter found for C++ type: %s" - , this->target_type.name())); + , this->target_type.name() + ) + ); PyErr_SetObject(PyExc_TypeError, msg.get()); diff --git a/src/converter/type_id.cpp b/src/converter/type_id.cpp index 74bcd39b..e1d95f0c 100644 --- a/src/converter/type_id.cpp +++ b/src/converter/type_id.cpp @@ -6,14 +6,111 @@ #include #include +#include +#include +#include +#include +#include +#include + #if !defined(__GNUC__) || __GNUC__ >= 3 || __SGI_STL_PORT # include #else # include #endif + +# ifdef BOOST_PYTHON_HAVE_GCC_CP_DEMANGLE +# if defined(__GNUC__) && __GNUC__ >= 3 +# include +# endif +#include +# endif + namespace boost { namespace python { +# ifdef BOOST_PYTHON_HAVE_GCC_CP_DEMANGLE +# ifdef __GNUC__ +# if __GNUC__ < 3 + +namespace cxxabi = :: ; +# else +namespace cxxabi = ::abi; // GCC 3.1 and later +# endif +# endif + +namespace +{ + struct compare_first_cstring + { + template + bool operator()(T const& x, T const& y) + { + return std::strcmp(x.first,y.first) < 0; + } + }; + + struct free_mem + { + free_mem(char*p) + : p(p) {} + + ~free_mem() + { + std::free(p); + } + char* p; + }; +} + +namespace detail +{ + BOOST_PYTHON_DECL char const* gcc_demangle(char const* mangled) + { + typedef std::vector< + std::pair + > mangling_map; + + static mangling_map demangler; + mangling_map::iterator p + = std::lower_bound( + demangler.begin(), demangler.end() + , std::make_pair(mangled, (char const*)0) + , compare_first_cstring()); + + if (p == demangler.end() || strcmp(p->first, mangled)) + { + int status; + free_mem keeper( + cxxabi::__cxa_demangle(mangled, 0, 0, &status) + ); + + assert(status != -3); // invalid argument error + + if (status == -1) + { + throw std::bad_alloc(); + } + else + { + char const* demangled + = status == -2 + // Invalid mangled name. Best we can do is to + // return it intact. + ? mangled + : keeper.p; + + std::cout << "demangled name: " << mangled << " as " << demangled << std::endl; + p = demangler.insert(p, std::make_pair(mangled, demangled)); + keeper.p = 0; + } + } + + return p->second; + } +} +# endif + BOOST_PYTHON_DECL std::ostream& operator<<(std::ostream& os, type_info const& x) { return os << x.name(); diff --git a/src/module.cpp b/src/module.cpp index 42bb7a8c..18a5061a 100644 --- a/src/module.cpp +++ b/src/module.cpp @@ -47,6 +47,9 @@ BOOST_PYTHON_DECL void init_module(char const* name, void(*init_function)()) namespace boost { namespace python { -BOOST_PYTHON_DECL PyObject* scope::current_scope = 0; +namespace detail +{ + BOOST_PYTHON_DECL PyObject* current_scope = 0; +} }}