Jon Olav Vik wrote:
> If I may make a wish, I would like Cython to find more declarations
> automatically. For instance, having
>
> cdef extern * from "cvode/cvode.h"
>
> or, if that is impractical,
>
> cdef extern from "cvode/cvode.h":
> CVodeCreate, CVRhsFn, CVodeMalloc, CVodeFree, CVode, CV_ADAMS, CV_BDF
Yes, we all would. If you find a decent CS student at your institution
who would like to do this as his or her master thesis then drop us a
note :-)
I think there's a script someone posted on the mailing list to try to
autogenerate pxds, though I don't remember enough to find it -- anyone?
> I haven't benchmarked anything yet, but the relative ease of adapting the C
> tutorial for CVODE [3] is uplifting. As a last question, what is the cleanest
> way to transfer arrays of double between realtype* and Numpy vectors (one-
> dimensional arrays)?
OK here it is. Note that this sets up the ndarray to point to the *same*
memory. Modifications to the resulting NumPy array will happen directly
in the NVector!
Case A: If you are 100% sure that you do not call N_VDestroy_Serial
before all references to the ndarray created are gone, you can simply do
this:
cdef extern from "numpy/arrayobject.h":
# These are simply missing from numpy.pxd due to laziness;
# so declare manually for now
void import_array()
object PyArray_SimpleNewFromData(int nd,
np.npy_intp* dims,
int typenum,
void* data)
import_array() # Needed because we call the raw NumPy C API below!
def some_func():
cdef np.npy_intp* shape = [somehow_extract_length_of(some_nvector)]
# Create ndarray. Assume realtype is double.
assert sizeof(realtype) == sizeof(double)
yourarray = PyArray_SimpleNewFromData(
1, shape, np.NPY_DOUBLE,
<void*>self.nvector.whatever_to_get_buffer_pointer)
...
But this is dangerous as the resulting yourarray will address
nonallocated memory if you free the underlying NVector.
Case B: Proper memory handling:
First, create a C header file (workaround.h), because Cython cannot
handle expressions of the form "foo(x) = y" so we need to "reformulate"
the NumPy C API a bit:
#include <numpy/arrayobject.h>
#define PyArray_Set_BASE(arr, obj) PyArray_BASE(arr) = obj
Then, this Cython code should do the job. Note that we need to create a
class because Python needs an object to associate with the memory, so
that the memory gets freed at the right time.
cimport numpy as np
cdef extern from "workaround.h":
void PyArray_Set_BASE(np.ndarray arr, object obj)
cdef extern from "numpy/arrayobject.h":
# These are simply missing from numpy.pxd due to laziness;
# so declare manually for now
void import_array()
object PyArray_SimpleNewFromData(int nd,
np.npy_intp* dims,
int typenum,
void* data)
import_array() # Needed because we call the raw NumPy C API below!
cdef class CythonNVector:
cdef N_Vector nvector
def __init__(self, length):
self.nvector = N_VNew_Serial(length)
def __dealloc__(self):
# Called when the object is being destroyed (normally there's
# no need for this in Python, but here it is, as we need to
# free C memory explicitly).
#
# Note: The "Python parts" of the object might already
# be gone in this method -- only touch C attributes.
N_VDestroy_Serial(self.nvector)
cpdef toarray(self):
cdef np.npy_intp* shape = \
[somehow_extract_length_of(self.nvector)]
# Create ndarray. Assume realtype is double.
assert sizeof(realtype) == sizeof(double)
cdef np.ndarray result = PyArray_SimpleNewFromData(
1, shape, np.NPY_DOUBLE,
<void*>self.nvector.whatever_to_get_buffer_pointer)
# Make the ndarray keep a reference to this object
PyArray_Set_BASE(result, self)
return result
Just modify this general scheme for your usecase (i.e. you can set
nvector manually rather than allocate it the constructor, etc.)
--
Dag Sverre
_______________________________________________
Cython-dev mailing list
[email protected]
http://codespeak.net/mailman/listinfo/cython-dev