On Mon, 2005-06-13 at 10:49 +0200, Dirk Meyer wrote: 
> I also have no clue. I always do the copy stuff. It is in pyimlib2 and
> mmpython and I don't know a good way to do this right. But Freevo
> should work without mevas installed into the system.

I just asked on #python and someone said the way to do it is to add
build/lib* to the PYTHONPATH if you want to run stuff directly from the
source tree.  I was skeptical, but he said that python's own build
system does it.  I downloaded Python from source and compiled it, and
when you run the binary from the source tree, sys.path is just magically
populated correctly.  I'm not really sure how it works.  I looked at
strace to get an idea of what files the interpreter opens on startup,
but couldn't see anything helpful.

Does anyone know how this works?

Well, in the meantime, I suppose the freevo script could just add stuff
to PYTHONPATH if it's being run from the source tree.

> You did something with a buffer object. I changed it to the current
> stuff. I tried to check all possible memory leaks and failures and may
> opinion was that it works. But it seems like this is wrong. So it was
> me, not you who did this. Please add some docs into the code how it
> works and why you are doing it this way. 

True, I don't think your way would have leaked memory.  But it was also
incorrect (because you couldn't call get_raw_data() with different
formats -- subsequent calls would give you the same data as the first
format), and it was very unpythony because it required a call to
free_raw_data().

There are basically two situations we run into with get_raw_data():

     1. The user requests native format (BGRA).  pyimlib2 can either
        allocate new memory and return a buffer from that, or create a
        buffer object from the pointer that
        imlib_image_get_data_for_reading_only() returns. 
     2. The user requests a non-native format (e.g. RGB).  pyimlib2 has
        to allocate new memory and return a buffer from that.

The second case is easy.  Just create a new buffer with PyBuffer_New,
which manages its own memory.  When the buffer object loses scope and
gets destroyed, the memory allocated for that buffer is deleted.

In the first case, if we allocate new memory, then the user can't write
to the pixels directly from python.  And anyway, we want to avoid the
unnecessary malloc and memcpy. If we create a buffer directly from the
pointer returned by Imlib2's api, the user has to make sure the Image
pyobject doesn't get destroyed while the buffer is alive.  But this is
horrible; Python has a refcount system, so let's use it.

So we want a buffer object which holds a reference to the Image
pyobject.  The way to do this is PyBuffer_FromObject().  In order for
this to work, Image_PyObject has to implement the buffer interface.  So
I added three functions to do that, prefixed with Image_PyObject_Buffer.
So if a read-only buffer is requested, it will call
imlib_image_get_data_for_reading_only() and return that pointer.   If a
writable buffer is requested, it will return the pointer from
imlib_image_get_data().  When this is called, Imlib2 seems to require
calling imlib_image_put_back_data() (which is implemented as
Imlib2.Image.put_back_raw_data()).  However if a user does fail to call
this function, nothing really bad will happen.  Memory will get cleaned
up correctly because all the proper refcounts are held.

I'll add some comments to the code to this effect.

Jason.

P.S.  Why is it that evolution spun out of control twice when writing
this email?  Like it seemed to get stuck in an endless loop of
mallocing.  By the time I managed to kill it, it had bloated to 800MB
and counting and causing my system to thrash horribly.  Sigh.  It's the
21st century, why does software still have to suck this bad?  </rant>

Attachment: signature.asc
Description: This is a digitally signed message part

Reply via email to