[C++-sig] TypeError: No to_python (by-value) converter found for C++ type: class std::basic_ostream<char, struct std::char_traits<char> >

Simon W simwarg at gmail.com
Thu Sep 30 16:38:50 CEST 2010


I don't quite understand your approach to 100%. But you gave me another
idea. Here's how it looks when I call python function:

        Uint32 serialise(const GameObject* obj, std::ostream& file)
        {
            if(boost::python::override f = get_override("serialise"))
            {
                // call python function and ask to return a str() of the
pickled bytes
                boost::python::str pickled =
f(boost::python::object(boost::python::ptr(obj)));
                tuple tup = make_tuple(pickled);
                std::string s = extract<std::string>(tup[0]);
                Uint32 size = s.size();

                // serialise the size of pickled object
                file.write((char*)&size, sizeof(Uint32));

                 // serialise pickled bytes as string
                file.write(s.c_str(), size);
                return size + sizeof(Uint32);
            }
        }
        Uint32    Python::ComponentSystem::deserialise(std::istream& file,
const GameObject* obj)
        {
            if(boost::python::override f = get_override("deserialise"))
            {
                Uint32 size = 0;

                // we must know how many bytes to extract
                file.read((char*)&size, sizeof(Uint32));

                // OK, here starts the conversion, but Im not quite sure how
to do exactly ...
                char* sbuf = new char[size];
                file.read(sbuf, size);
                std::string sdata(sbuf);

                boost::python::object data(sdata); // ERROR:
UnicodeDecodeError: 'utf8' codec can't decode bytes in position 80-85:
unsupported Unicode code range

                // send the chunk of bytes/string to the deserialise python
function and let it handle the restore of object
                f(boost::python::object(boost::python::ptr(obj)), data);
            }

            return  sizeof(Uint32) + size;
        }

And the python script:
    def serialise(self, gameobj):
        if(gameobj in self.components):
            return str(pickle.dumps(self.components[gameobj]))

        return 0

    def deserialise(self, gameobj, data):
        pass

On Wed, Sep 29, 2010 at 4:02 PM, Jakub Zytka <kubol at kormoran.net> wrote:

> On 09/29/10 14:11, Simon W wrote:
>
>> Thank you for the answer. Is there any way I can prevent it from copying
>> the
>> stream object even though std::ostream::write() returns a std::ostream& ?
>>
> You can use other return policy, or define one on your own.
>
>
> http://www.boost.org/doc/libs/1_44_0/libs/python/doc/tutorial/doc/html/python/functions.html#python.call_policies
>
> But honestly, I do not think it is the correct way to go. Read below.
>
> > I'm trying to serialise some data. I have a c++ class:
> >          class ostream
> >          {
> > ...
> > could to the c++ way and add a integer before the byte stream that reveal
> how
> > big it is. But How can i serialise an int from python that takes up
> constant
> > "byte-size" for an integer between lets say 0-10000!?
> Everything can be done, but I have a different question:
> I haven't followed all your previous emails, but do you *really* need to
> implement serialization code in python?
> Somehow I feel it is very weird that on one hand you want to have
> serialization code in python, and yet use ostream.
>
> What would be wrong with coding serialization purely in C++, and then
> providing appropriate pickle suite to python:
> struct MyPickleSuite
> {
> // ...
> boost::python::tuple MyPickleSuite::getstate(MyClass & object)
> {
> std::ostringstream oStream(ios_base::binary);
> serialize(oStream, object);
> return boost::python::make_tuple(oStream.str());
> }
>
> void MyPickleSuite::setstate(MyClass & object, boost::python::tuple state)
> {
> // verify tuple correctness etc.
> std::string serializedData = extract<std::string>(state[0]);
> std::istringstream iStream(serializedData, ios_base::binary);
> serialize(iStream, object); // NOTE: you can use the same code for
> serialization and deserialization. stream type should determine actual
> behavior
> }
> }
>
> That way you do not have to expose ostream to python at all. In fact if you
> wanted to switch to another type of stream (imagine that you have a custom
> stream implementation, which provides eg. type checking) it is cheap. You
> only change a few functions in your pickle suite, nothing more.
>
> Even if you do really need to define serialization in python I see no
> reason to play with streams. I'd rather had a wrapper which hides underlying
> implementation (eg. std::streams) and operates on strings.
>
> Please reconsider your design.
>
> _______________________________________________
> Cplusplus-sig mailing list
> Cplusplus-sig at python.org
> http://mail.python.org/mailman/listinfo/cplusplus-sig
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/cplusplus-sig/attachments/20100930/76dc5347/attachment.html>


More information about the Cplusplus-sig mailing list