Opened 13 years ago

Closed 13 years ago

#4003 closed Bugs (fixed)

Error in destroy.hpp when methods "T()" and "operator~()" are defined.

Reported by: Christopher Bruns <cmbruns@…> Owned by: Dave Abrahams
Milestone: Boost 1.43.0 Component: python USE GITHUB
Version: Boost 1.42.0 Severity: Problem
Keywords: Cc: cmbruns@…

Description

I am wrapping a large library using boost python and Py++. I encountered a peculiar situation with one of the wrapped classes.

I have attached a minimal example and an imperfect patch (see below).

The problem occurs on line 33 of boost/python/detail/destroy.hpp:

unpatched version:
=================
30    template <class T>
31    static void execute(T const volatile* p)
32    {
33        p->T::~T();
34    }

The problem is that the class being wrapped has a member function "T()", and the class returned by that function has an "operator~()"; which leads to a compile error. I have been working around this for the past year by patching the file destroy.hpp to use the name "Type" instead of "T" in this section, each time I install a new version of boost.

patched version:
===============
30    template <class Type>
31    static void execute(Type const volatile* p)
32    {
33        p->Type::~Type();
34    }

That's not a complete solution, of course. I suspect I could concoct another scenario with classes that have a "Type" method etc. But it solves the problem for me with the libraries I am actually wrapping. Perhaps you C++ gurus could come up with a more robust approach.

With the patch in place, my module compiles. Without the patch, I get these compiler messages:

############################################################# building 'foo_module' extension C:\Program Files\Microsoft Visual Studio 9.0\VC\BIN\cl.exe /c /nologo /Ox /MD /W3 /GS - /DNDEBUG "-IC:/Program Files/boost/boost_1_42" -I. -Ic:\Python26\include -Ic:\Pytho n26\PC /Tpwrap_foo.cpp /Fobuild\temp.win32-2.6\Release\wrap_foo.obj /EHsc -D"_HAS_TR1 =0" wrap_foo.cpp C:/Program Files/boost/boost_1_42\boost/python/detail/destroy.hpp(33) : error C2523: 'Foo3::~T' : destructor tag mismatch

C:/Program Files/boost/boost_1_42\boost/python/detail/destroy.hpp(95) : see reference to function template instantiation 'void boost::python::detail::value_destroyer<false>::execute<const T>(volatile const T *)' being compiled with [

T=const Foo3

] C:/Program Files/boost/boost_1_42\boost/python/detail/destroy.hpp(101) : see reference to function template instantiation 'void boost::python::detail::destroy_referent_impl<T>(void *,T &(cdecl *)(void))' being compiled with [

T=const Foo3

] C:/Program Files/boost/boost_1_42\boost/python/converter/rvalue_from_python_data.hpp(135) : see reference to function template instantiation 'void boost::python::detail::destroy_referent<const Foo3&>(void *,T (cdecl *)(void))' being compiled with [

T=const Foo3 &

] C:/Program Files/boost/boost_1_42\boost/python/converter/rvalue_from_python_data.hpp(133) : while compiling class template member function 'boost::python::converter::rvalue_from_python_data<T>::~rvalue_from_python_data(void)' with [

T=const Foo3 &

] C:/Program Files/boost/boost_1_42\boost/python/converter/arg_from_python.hpp(124) : see reference to class template instantiation 'boost::python::converter::rvalue_from_python_data<T>' being compiled with [

T=const Foo3 &

] C:/Program Files/boost/boost_1_42\boost/python/arg_from_python.hpp(27) : see reference to class template instantiation 'boost::python::converter::arg_rvalue_from_python<T>' being compiled with [

T=const Foo3 &

] C:/Program Files/boost/boost_1_42\boost/preprocessor/iteration/detail/local.hpp(37) : see reference to class template instantiation 'boost::python::arg_from_python<T>' being compiled with [

T=const Foo3 &

] C:/Program Files/boost/boost_1_42\boost/python/detail/caller.hpp(200) : while compiling class template member function 'PyObject *boost::python::detail::caller_arity<2>::impl<F,Policies,Sig>::operator ()(PyObject *,PyObject *)' with [

F=void (thiscall Foo4::* )(const Foo3 &), Policies=boost::python::default_call_policies, Sig=boost::mpl::vector3<void,Foo4 &,const Foo3 &>

] C:/Program Files/boost/boost_1_42\boost/python/detail/caller.hpp(169) : see reference to class template instantiation 'boost::python::detail::caller_arity<2>::impl<F,Policies,Sig>' being compiled with [

F=void (thiscall Foo4::* )(const Foo3 &), Policies=boost::python::default_call_policies, Sig=boost::mpl::vector3<void,Foo4 &,const Foo3 &>

] C:/Program Files/boost/boost_1_42\boost/python/make_function.hpp(61) : see reference to class template instantiation 'boost::python::detail::caller<F,CallPolicies,Sig>' being compiled with [

F=void (thiscall Foo4::* )(const Foo3 &), CallPolicies=boost::python::default_call_policies, Sig=boost::mpl::vector3<void,Foo4 &,const Foo3 &>

] C:/Program Files/boost/boost_1_42\boost/python/make_function.hpp(146) : see reference to function template instantiation 'boost::python::api::object boost::python::detail::make_function_aux<F,CallPolicies,Signature,boost::mpl::int_<N>>(F,const CallPolicies &,const Sig &,const boost::python::detail::keyword_range &,NumKeywords)' being compiled with [

F=void (thiscall Foo4::* )(const Foo3 &), CallPolicies=boost::python::default_call_policies, Signature=boost::mpl::vector3<void,Foo4 &,const Foo3 &>, N=1, Sig=boost::mpl::vector3<void,Foo4 &,const Foo3 &>, NumKeywords=boost::mpl::int_<1>

] C:/Program Files/boost/boost_1_42\boost/python/class.hpp(544) : see reference to function template instantiation 'boost::python::api::object boost::python::make_function<Fn,boost::python::default_call_policies,T1,boost::mpl::vector3<T0,Foo4 &,T2>>(F,const CallPolicies &,const Keywords &,const Signature &)' being compiled with [

Fn=void (thiscall Foo4::* )(const Foo3 &), T1=boost::python::detail::keywords<1>, T0=void, T2=const Foo3 &, F=void (thiscall Foo4::* )(const Foo3 &), CallPolicies=boost::python::default_call_policies, Keywords=boost::python::detail::keywords<1>, Signature=boost::mpl::vector3<void,Foo4 &,const Foo3 &>

] C:/Program Files/boost/boost_1_42\boost/python/class.hpp(614) : see reference to function template instantiation 'void boost::python::class_<W>::def_impl<Foo4,Fn,boost::python::detail::def_helper<T1>>(T *,const char *,Fn,const Helper &,...)' being compiled with [

W=Foo4, Fn=void (thiscall Foo4::* )(const Foo3 &), T1=boost::python::detail::keywords<1>, T=Foo4, Helper=boost::python::detail::def_helper<boost::python::detail::keywords<1>>

] C:/Program Files/boost/boost_1_42\boost/python/class.hpp(244) : see reference to function template instantiation 'void boost::python::class_<W>::def_maybe_overloads<A1,A2>(const char *,Fn,const boost::python::detail::keywords<1> &,...)' being compiled with [

W=Foo4, A1=void (thiscall Foo4::* )(const Foo3 &), A2=boost::python::detail::keywords<1>, Fn=void (thiscall Foo4::* )(const Foo3 &)

] wrap_foo.cpp(21) : see reference to function template instantiation 'boost::python::class_<W> &boost::python::class_<W>::def<void(thiscall Foo4::* )(const Foo3 &),boost::python::detail::keywords<1>>(const char *,A1,const A2 &)' being compiled with [

W=Foo4, A1=void (thiscall Foo4::* )(const Foo3 &), A2=boost::python::detail::keywords<1>

]

error: command '"C:\Program Files\Microsoft Visual Studio 9.0\VC\BIN\cl.exe"' failed with exit status 2 #########################################################

Attachments (4)

foo.h (266 bytes ) - added by Christopher Bruns <cmbruns@…> 13 years ago.
minimized example header file to be wrapped
wrap_foo.cpp (634 bytes ) - added by Christopher Bruns <cmbruns@…> 13 years ago.
boost.python wrapping code for minimal example
wrap_foo.2.cpp (634 bytes ) - added by Christopher Bruns <cmbruns@…> 13 years ago.
boost.python wrapping code for minimal example
inadequate_patch.patch (405 bytes ) - added by Christopher Bruns <cmbruns@…> 13 years ago.
(imperfect) patch for destroy.hpp

Download all attachments as: .zip

Change History (10)

by Christopher Bruns <cmbruns@…>, 13 years ago

Attachment: foo.h added

minimized example header file to be wrapped

by Christopher Bruns <cmbruns@…>, 13 years ago

Attachment: wrap_foo.cpp added

boost.python wrapping code for minimal example

by Christopher Bruns <cmbruns@…>, 13 years ago

Attachment: wrap_foo.2.cpp added

boost.python wrapping code for minimal example

by Christopher Bruns <cmbruns@…>, 13 years ago

Attachment: inadequate_patch.patch added

(imperfect) patch for destroy.hpp

comment:1 by Christopher Bruns <cmbruns@…>, 13 years ago

Sorry about the two copies of wrap_foo.cpp. In my impatience I hit the "submit" button twice.

comment:2 by Steven Watanabe, 13 years ago

It seems to work if I change the code to

p->~T()

However, this is slightly different, since it will invoke a virtual destructor, where the original will not. The only other alternative I can think of it to mangle the name so that there is no chance of anyone using the same name. (i.e. template<class T_boost_python_unique_id_82623817364646282>)

comment:3 by Dave Abrahams, 13 years ago

Owner: changed from Dave Abrahams to Steven Watanabe

Isn't using a virtual d'tor OK here?

What about a simple typedef either inside the function body or in the body of the class? Does VC still look up the wrong name?

comment:4 by Steven Watanabe, 13 years ago

Owner: changed from Steven Watanabe to Dave Abrahams

I would assume that a virtual destructor is okay, but I didn't write the code in question. A typedef doesn't seem to help. The first name after the -> always seems to be looked up in the context of T first. I even tried this:

template<class T>
struct Destroyer {
    typedef T Type;
    static void destroy(T* t) {
        t->Destroyer<Type>::Type::~Type();
    }
};

struct S {
    void Type();
    void Destroyer();
};

int main() {
    S t;
    Destroyer<S>::destroy(&t);
}

and it still fails.

in reply to:  4 comment:5 by anonymous, 13 years ago

Replying to steven_watanabe:

I would assume that a virtual destructor is okay, but I didn't write the code in question.

Feel free to check in your fix, preferably after having run the tests once :-)

comment:6 by Steven Watanabe, 13 years ago

Resolution: fixed
Status: newclosed

(In [60868]) Handle the destructor call in a way that keeps msvc happy. Fixes #4003

Note: See TracTickets for help on using tickets.