[Pyrex] Allocating an array.array of a specific length in pyrex

Chris Lambacher lambacck at gmail.com
Wed Jun 8 20:56:29 CEST 2005


And we have a winner.

For reference the final code is below.

Thanks for your help,
-Chris

import array
cdef extern from "Python.h":
    int PyObject_AsWriteBuffer(object obj, void **buffer, int *buffer_len)
    int PyObject_AsReadBuffer(object obj, void **buffer, int *buffer_len)
    object PyString_FromStringAndSize(char *, int)
    char *PyString_AsString(object obj)

cdef int get_w_buffer(obj, unsigned char **data, int *length) except -1:
    cdef int result
    cdef void *vd
    # use a void *
    result = PyObject_AsWriteBuffer(obj, &vd, length)
    data[0] = <unsigned char *>vd
    return result

cdef int get_r_buffer(obj, unsigned char **data, int *length) except -1:
    cdef int result
    cdef void *vd
    # use a void *
    result = PyObject_AsReadBuffer(obj, &vd, length)
    data[0] = <unsigned char *>vd
    return result

def encode(int w, int h, in_a):
    cdef unsigned int pixels, a_off, str_off#, buffer_len
    cdef int res, inlen, buffer_len
    cdef unsigned char *in_str, *out_str
    
    res = get_r_buffer(in_a, &in_str, &inlen)
    if res:
        raise Exception, "Could not get a readable buffer from the input"


    pixels = w * h
    a = PyString_FromStringAndSize(NULL, pixels * 2)
    out_str = <unsigned char *> PyString_AsString(a)
    buffer_len = pixels * 2

    str_off = 0
    a_off = 0
    while a_off < buffer_len and str_off < inlen:
        out_str[a_off] = in_str[str_off]
        out_str[a_off+1] = (in_str[str_off+1] + in_str[str_off+4])/2
        out_str[a_off+2] = in_str[str_off+3]
        out_str[a_off+3] = (in_str[str_off+2] + in_str[str_off+5])/2

        str_off = str_off + 6
        a_off = a_off + 4
    
    return a



On 6/8/05, Chris Lambacher <lambacck at gmail.com> wrote:
> I replaced:
> a = array.array('B', , [0] * (pixels * 2))
> with:
> a = PyString_FromStringAndSize(NULL, pixels * 2)
> 
> and got:
> C:\work\testing\plink_o_ip>python ycbycr.py
> Traceback (most recent call last):
>   File "ycbycr.py", line 62, in ?
>     ycbycr = image2ycbycr(im)
>   File "ycbycr.py", line 38, in image2ycbycr
>     return _ycbycr.ycbcr2ycbycr(w, h, ycbcrim.tostring())
>   File "_ycbycr.pyx", line 42, in _ycbycr.ycbcr2ycbycr
>     res = get_w_buffer(a, &out_str, &buffer_len)
> TypeError: Cannot use string as modifiable buffer
> 
> Strings are not mutable so this is not going to work for me :(
> 
> Is there a way to allocate a python buffer object and give that to
> array.array or a string object?
> 
> -Chris
> 
> On 6/8/05, Chris Lambacher <lambacck at gmail.com> wrote:
> > The memory is not temporary, I am passing it out as an array, thus the
> > malloc/free route will require double allocation(once for malloc/free,
> > once for array.array).  I am not using string because when I tried to
> > pass the data in as string, pyrex complained about the conversion.
> > However, I could probably use the same PyObject_AsReadBuffer function
> > call to get at the data passed in to the function as a string and then
> > pass it out as a string as well using the interface suggested (
> > PyString_FromStringAndSize and PyString_AsString ).  Perhapse I need
> > to substitute PyObject_AsWriteBuffer instead of PyString_AsString in
> > order for my changes to get propegated back to the string object?
> >
> > -Chris
> >
> >
> > On 6/8/05, Adam Langley <alangley at gmail.com> wrote:
> > > On 6/8/05, Chris Lambacher <lambacck at gmail.com> wrote:
> > > > My question is, is there a better way to
> > > > allocate the memory for the array.array object than:
> > > >       a = array.array('B', [0] * (pixels * 2))
> > >
> > > cdef unsigned char *buffer
> > > temp_string = PyString_FromStringAndSize(NULL, length)
> > > buffer = <unsigned char *> PyString_AsString(temp_string)
> > >
> > > That's one way to do it. But it looks like you just want an area of
> > > memory so why not:
> > >
> > > cdef extern from "stdlib.h":
> > >   ctypedef unsigned long size_t
> > >   void *malloc(size_t size)
> > >   void free(void *mem)
> > >
> > > ?
> > >
> > > AGL
> > >
> > > --
> > > Adam Langley                                      agl at imperialviolet.org
> > > http://www.imperialviolet.org                       (+44) (0)7906 332512
> > > PGP: 9113   256A   CC0F   71A6   4C84   5087   CDA5   52DF   2CB6   3D60
> > >
> >
> >
> > --
> > Christopher Lambacher
> > lambacck at computer.org
> >
> 
> 
> --
> Christopher Lambacher
> lambacck at computer.org
> 


-- 
Christopher Lambacher
lambacck at computer.org



More information about the Pyrex mailing list