[C++-sig] Re: Converting CString to/from std::string

David Abrahams dave at boost-consulting.com
Wed Sep 24 22:30:59 CEST 2003


Martin Blais <blais at iro.umontreal.ca> writes:

> Me again.
>
> I wrapped up the ugly bits of the automated conversion to do some of
> the cooking automatically.  I use it like this, for an hypothetical
> MyPath class for which I want to declare automatic conversion to/from
> a string (without exposing MyPath)::
>
>    template <>
>    python::object AutoConverter<MyPath>::toObject( MyPath const& s )
>    {
>       return python::str( s.cstr() );
>    }
>
>    template <>
>    void* AutoConverter<MyPath>::convertible( PyObject* obj_ptr )
>    {
>       if ( !PyString_Check(obj_ptr) ) return 0;
>       return obj_ptr;
>    }
>
>    template <>
>    void AutoConverter<MyPath>::fromPython(
>       PyObject* obj_ptr,
>       void*     memblock
>    )
>    {
>       const char* value = PyString_AsString( obj_ptr );
>       if (value == 0) {
>          python::throw_error_already_set();
>       }
>       new ( memblock ) MyPath( value );
>    }
>
> Then in my initmodule definition I add::
>
>    ...
>    AutoConverter<MyPath>();
>    ...
>
>
> I tested this with MSVC7.1 (2003/.NET) on Windows XP.  Works for me,
> does the gig for now.

It's an interesting interface, the idea of using member function
specialization to provide the functionality.  The downside is that a
failure to implement the member functions shows up only at runtime.
If you left out the default implementations, you could get it to fail
at link time, but I'd much rather see a solution that fails at compile
time.  It's easy enough to do.

Another minor issue is that your converters force you to register
conversions in both directions (not always desired), and only handle
rvalue from-python conversions.  That may be what most people want,
most of the time... though I'm not sure.

> But somehow, I feel like I'm not doing something right, there must be
> a better way to do this.  I'm sure Dave thought about some way for
> automatic conversions to occur but I am not finding it.

Well, not really anything beyond the low-level facilities your little
wrapper takes advantage of.

> (Dave: feel free to massage and include the file in attachment to
> Boost.Python, if you think it's worth anything.)

Well, it's got at least one serious problem:

> template <class T>
> void AutoConverter<T>::construct(
>    PyObject* obj_ptr,
>    python::converter::rvalue_from_python_stage1_data* data
> )
> {
>    // This should be exception-safe if the conversion fails (i.e. auto_ptr will
>    // take care of freeing memory.
>    std::auto_ptr<char> storage(
>       reinterpret_cast< python::converter::rvalue_from_python_storage<T>* >(
>          data
>       )->storage.bytes
>    );

This whole statement is just wrong.  You shouldn't be using
reinterpret_cast (static_cast through void* or plain-old C-style cast
will do) and you *definitely* shouldn't be trying to manage that
memory with an auto_ptr.  It's owned elsewhere.


-- 
Dave Abrahams
Boost Consulting
www.boost-consulting.com





More information about the Cplusplus-sig mailing list