On Mon, Oct 13, 2008 at 3:38 PM, Dag Sverre Seljebotn
<[EMAIL PROTECTED]> wrote:
> Ondrej Certik wrote:
>> Hi,
>>
>> what is now the canonical way to convert between (python) numpy array and
>>
>> int *a
>>
>> or
>>
>> double *a
>>
>> ?
>>
> Yes, this should probably be fixed/be made more available.
>
> The simplest thing is something like the (untested) code below. It is
> certainly possible to do some C calls instead of Python calls here (like
> petsc4py does); however I tink this definitely belong to the 80% of the
> code that only takes 20% of the time; Cython seems to be more about
> optimizing the other part that tends to get repeated :-)
>
> import numpy as np
> arr = some generic numpy array
> assert arr.dtype == np.float64 # or whatever
> cdef ndarray contarr
> if not arr.flags['C_CONTIGUOUS']:
> # Array is not contiguous, need to make contiguous copy
> contarr = arr.copy(order='C')
> else:
> contarr = arr
> # Get data pointer. Important that contarr is cdef-ed ndarray
> cdef npy.float64_t* ptr = <npy.float64_t*>contarr.data
> call_c_function(ptr)
> # If the C function modifies the data, and the array was not contiguous,
> # then the data of contarr must be copied into arr, using standard NumPy
> calls:
> arr[:] = contarr[:]
>
> Comment: The only "shady" part here is "contarr.data", which accesses
> implementation details of NumPy arrays. I'm guessing that this will
> never change, but I once planned to make a generic cython function
> "cython.buffer.bufptr" which would return the same pointer but it could
> be acquired through the buffer API.
>
> Note that the code above does not make use of the buffer API, as it is
> written to work regardless of number of dimensions.
Currently I use these methods:
cdef inline ndarray array_d(int size, double *data):
#cdef ndarray ary2 = PyArray_ZEROS(1, &size, 12, 0)
cdef ndarray ary = zeros(size, dtype=float64)
if data != NULL: memcpy(ary.data, data, size*sizeof(double))
return ary
cdef inline int iarray_d(ndarray a, int *size, double **data) except -1:
if a.dtype != float64:
raise TypeError("The array must have the dtype=float64.")
if size!=NULL: size[0] = a.dimensions[0]
if data!=NULL: data[0] = <double *> (a.data)
If I uncomment the commented out line (i.e. to call numpy C/API
directly instead of through Python), I'll get a segfault. I haven't
figured out yet why. But nevertheless, the current version works.
Ondrej
_______________________________________________
Cython-dev mailing list
[email protected]
http://codespeak.net/mailman/listinfo/cython-dev