[C++-sig] question about implicit type conversion of vector to a custom type

Grant Tang grant.tang at gmail.com
Thu Aug 18 18:37:21 CEST 2011


"Jim Bosch"  wrote in message news:4E4AD9D9.9000501 at gmail.com...

>Unfortunately, there's no "best-match" type checking in Boost.Python; when 
>trying to convert a Python object to a particular C++ type, it simply runs 
>over a list of all the converters registered (using RTTI) for that C++ 
>type.
>
>Each of those converters then gets a chance to check whether it "matches" 
>the Python object; if it thinks it does, none of the other converters get 
>tried.
>
>I'd guess that's what's happening to you - implicitly_convertible doesn't 
>really do enough work in that match stage, so the first conversion you've 
>registered says "I match!" and then fails by throwing an exception.
>
>The fix might be in how you've written your vector<> conversions; when 
>given a list or tuple that contains the wrong element type, they need to 
>report that they "don't match", rather than matching any list or tuple and 
>then throwing an exception when the element type is incorrect.
>
>Good luck!
>
>Jim Bosch

I change my vector<> conversion(see it in my last reply) to add 
specialization for int, float, string etc.
I added type check in convertible() function:

    template <>
    struct vector_from_python <float>
    {
        vector_from_python()
        {
            python::converter::registry::push_back(&convertible, &construct,
                                                   python::type_id<vector<float> 
 >());
        }

        static void* convertible(PyObject* obj_ptr)
        {
            if (!(PyList_Check(obj_ptr) || PyTuple_Check(obj_ptr)
                  || PyIter_Check(obj_ptr)  || PyRange_Check(obj_ptr))) {
                return 0;
            }

            PyObject * first_obj = PyObject_GetItem(obj_ptr, 
PyInt_FromLong(0));
            if( !PyObject_TypeCheck(first_obj, &PyFloat_Type) ) {
                return 0;
            }

            return obj_ptr;
        }


        static void construct(PyObject* obj_ptr,
                              python::converter::rvalue_from_python_stage1_data* 
data)
        {
            void* storage =
((python::converter::rvalue_from_python_storage<vector<float> >*)
                             data)->storage.bytes;
            new (storage) vector<float>();

            data->convertible = storage;

            vector<float>& result = *((vector<float>*) storage);

            python::handle<> obj_iter(PyObject_GetIter(obj_ptr));

            while(1) {
                python::handle<>
py_elem_hdl(python::allow_null(PyIter_Next(obj_iter.get())));
                if (PyErr_Occurred()) {
                    python::throw_error_already_set();
                }

                if (!py_elem_hdl.get()) {
                    break;
                }

                python::object py_elem_obj(py_elem_hdl);
                python::extract<float> elem_proxy(py_elem_obj);
                result.push_back(elem_proxy());
            }
        }
    };

This time the implicit type conversion works perfectly. But I got a new 
problem: the memory leak!
The memory leak happens only for float type, whenever I convert the float 
list in python to vector
of float in c++, the memory for float list is leaked. I put the call in a 
function, and called the gc.collect()
after exit the function, the memory is still not recycled.

Why is the memory of the python list is not freed after exit the scope?

Grant 




More information about the Cplusplus-sig mailing list