On Apr 11, 2008, at 1:16 AM, Dag Sverre Seljebotn wrote:
>
>> The main idea (Lisandro came up with this) is to build these
>> capabilities into cython itself by introducing the following syntax:
>>
>> cdef foo(size):
>>   cdef double a[size]    # This is like the dynamic arrays in C99
>>   # do stuff with a, but don't worry about deallocating the memory!!!

I really like this syntax, and it seems easy enough to support. One  
could then even do things like "for x in a" correctly, do bounds  
checking (or should we let the user shoot themselves in the foot for  
speed--or perhaps it could usually be optimized away), and coerce it  
too (or from?) a Python object.

It has one drawback, which is that it can never be re-sized, and nor  
can it be used in any control structures (e.g. inside an if statement  
or loop).

> It sure looks like it would be convenient; but I'll take the role  
> as an
> advocate against it :-)
>
> 1) Having "cdef double a[size]" allocate anything is very against the
> Python syntax -- nothing is ever allocated in Python without a  
> function
> call and an assignment (same as in Java). To somebody who comes from a
> strict Python background and not C, it really looks like only a  
> variable
> type declaration, not object allocation. In Cython, this Python way of
> working is mostly kept, and this would be a step *away* from Python in
> terms of the "feel" of the language.

It looks like cdef double a[10], which is currently legal.

> 2) This kind of duplicates the behaviour of the "with" keyword  
> (which is
> not present in Cython today (either), but definitely is a goal, and is
> present in current Python).
>
> However, using the with keyword would be a bit less convenient, given
> function template support and with keyword support in Cython it could
> look something like this:
>
> with carray(double, size) as buf:
>   cdef double* a = buf.data
>    # do stuff with a
>
> If you want a different memory allocator, simply use a different
> function than carray...
>
> 3) Long-term Python users with very little C experience might end up
> doing something like
>
> cdef double a[size]
> # fill in a
> return a

If the return type is double*, an error can be given at compile time,  
and if it's object it could even coerce to a Python list. I would say  
a can neither be assigned to or used as an assignment to something  
else--just indexed.

> (Or, some more complex variant that we can't emit a warning for). With
> the "with" keyword however, Python users will *know* not to return a.

I think it will be less clear that a is volatile, as it doesn't show  
up in the with statement at all (and imagine if the assignment were  
made much later).

> (*) This is assuming a new carray template function as well, and so
> assumes even more Cython development. One might have to type "a" as  
> well
> but with type inference it might look something like the above.
>
> 3) Just an overall comment: I personally think NumPy arrays are
> excellent for this. I'd have no problems personally with using a NumPy
> array only in order to allocate memory and then pass that memory on  
> to a
> C library for instance. (The problem is, I suppose, having to  
> depend on
> the NumPy library...though investing effort in creating a garbage
> collected array type when NumPy already has that seems too much like
> reinventing the wheel to me.) This will become more convenient than
> today if Cython grows better NumPy support.

One can make something much lighter weight than numpy--the  
PyString_FromStringAndLength example that started this thread is  
*much* faster than creating a NumPy array, let alone a call to malloc 
() and free(). Although I don't anticipate using Cython much without  
having NumPy around, I don't want to make it a requirement for  
effectively using Cython.

>> 3) The trick is to make sure that free(private_ptr) is called when  
>> the
>> function's scope is finished.  How can this be done.  One way  
>> would be
>> to have a private/hidden python object (it would have to be a C
>> extension type) that 1) hold's private_ptr as an attribute and 2)
>> calls free(private_ptr) when it is garbage collected.
>>
> This is very trivially implemented by having Cython automatically wrap
> the function with try/finally prior to generating C code. Not going to
> be a problem at all. (But it can be done the way you say as well...)

It's even easier than that, the generated functions all have a single  
exit point (once they've successfully parsed arguments at least) that  
does cleanup code (such as deallocate any remaining temp variables,  
etc.). This could just be added here.

- Robert


_______________________________________________
Cython-dev mailing list
Cython-dev@codespeak.net
http://codespeak.net/mailman/listinfo/cython-dev

Reply via email to