Dag Sverre Seljebotn <da...@...> writes:
> > Do I really have to replicate the entire struct definition?
>
> No, you just have to write "enough" for Cython to know what C code to
> output. Knowing what that is probably takes some C experience though;
> I'll try to help.
>
> First, the #if-s cannot be expressed in Cython, but Cython is going in
> the direction of the type of external typedefs not to matter. I think
> you can safely do
>
> cdef extern from ...:
> ctypedef double realtype
>
> It should work also when Sundials is compiled with float or long double.
>
> Then N_Vector etc. can probably be expressed like this:
>
> cdef extern from ....:
> cdef struct _generic_N_Vector:
> void* content
> # not necesarry to declare ops unless you will be using
> # the contents of ops from Cython
>
> ctypedef _generic_N_Vector* N_vector
>
> N_Vector N_VNew_Serial(long int vec_length)
>
> Then you will be able to do
>
> cdef NVector v = N_VNew_Serial(10)
> cdef realtype* v_data = <realtype*>v.content
> v_data[0] = 34
Thank you so much! This seems to work well [1] after some adjustments, and I've
even been able to print and modify the contents of an N_Vector.
* I found I had to add libraries=['sundials_cvode', 'sundials_nvecserial'] to
get at the N_Vector functions. (Otherwise, the module compiled without error
but failed on import with "ImportError: ./hello.so: undefined symbol:
N_VNew_Serial".)
* I needed to cast v.content to <N_VectorContent_Serial>, not to <realtype*>.
N_VectorContent_Serial is a struct with a .data field which apparently is what
I'm after. [2]
* When trying to ctypedef N_VectorContent_Serial, I didn't realize it resided
in another header file. Until I fetched it with 'cdef extern from "nvector/
nvector_serial.h"', I got these warnings (which I won't ignore again 8-):
hello.c:418: warning: implicit declaration of function 'N_VNew_Serial'
hello.c:418: warning: assignment makes pointer from integer without a cast
hello.c:436: warning: implicit declaration of function 'N_VPrint_Serial'
hello.c:476: warning: implicit declaration of function 'N_VDestroy_Serial'
Thanks a lot for your help so far!
Best regards,
Jon Olav
[1]
== compilation, running, output ==
bash-3.2$ rm -rf build hello.so hello.c && python setup.py build_ext --inplace
&& python -c "import hello"
running build_ext
cythoning hello.pyx to hello.c
building 'hello' extension
creating build
creating build/temp.linux-x86_64-2.5
gcc -pthread -fno-strict-aliasing -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-
prototypes -fPIC -I/site/VERSIONS/sundials-2.3.0/include -I/site/VERSIONS/
compython-2.5/Linux/include/python2.5 -c hello.c -o build/temp.linux-x86_64-2.5/
hello.o
gcc -pthread -shared build/temp.linux-x86_64-2.5/hello.o -L/site/VERSIONS/
sundials-2.3.0/lib -L/site/VERSIONS/compython-2.5/Linux/lib -lsundials_cvode -
lsundials_nvecserial -lpython2.5 -o hello.so
1.1297001e-312
1.1297001e-312
2.3547898e-310
0
1
2
== hello.pyx ==
"""Trying to modify an NVector"""
cdef extern from "sundials/sundials_types.h":
ctypedef double realtype
cdef extern from "sundials/sundials_nvector.h":
cdef struct _generic_N_Vector:
void* content
ctypedef _generic_N_Vector* N_Vector
N_Vector N_VNew_Serial(long int vec_length)
void N_VDestroy_Serial(N_Vector v)
void N_VPrint_Serial(N_Vector v)
cdef extern from "nvector/nvector_serial.h":
cdef struct _N_VectorContent_Serial:
long int length
realtype* data
ctypedef _N_VectorContent_Serial* N_VectorContent_Serial
cdef N_Vector v = N_VNew_Serial(3)
cdef realtype* v_data = (<N_VectorContent_Serial>v.content).data
N_VPrint_Serial(v) # prints uninitialized floats
for i in range(3):
v_data[i] = i
N_VPrint_Serial(v) # prints 0, 1, 2
N_VDestroy_Serial(v)
== setup.py ==
"""Run with e.g. python setup.py build_ext --inplace
Or, to remove intermediate files from previous builds:
rm -rf build hello.so hello.c && python setup.py build_ext --inplace && python -
c "import hello"
"""
from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext
setup(
cmdclass = {'build_ext': build_ext},
ext_modules = [
Extension("hello",
["hello.pyx"],
include_dirs=['/site/VERSIONS/sundials-2.3.0/include'],
library_dirs=['/site/VERSIONS/sundials-2.3.0/lib'],
libraries=['sundials_cvode', 'sundials_nvecserial']),
]
)
[2]
This is what showed the problem in treating v.content as an array of double,
"cdef realtype* v_data = <realtype*>v.content". Before I modified v_data[0],
N_VPrint_Serial() would correctly print the (uninitialized) floats in the
vector. After modifying v_data[0], it printed uninitialized floats ad infinitum.
Looking at the source code of N_VPrint_Serial() [3], I saw that it used the
macros NV_LENGTH_S and NV_DATA_S, which accessed fields of the struct type
N_VectorContent_Serial.
== excerpt from nvector_serial.h ==
#define NV_CONTENT_S(v) ( (N_VectorContent_Serial)(v->content) )
#define NV_LENGTH_S(v) ( NV_CONTENT_S(v)->length )
void N_VPrint_Serial(N_Vector x)
{
long int i, N;
realtype *xd;
N = NV_LENGTH_S(x);
xd = NV_DATA_S(x);
for (i=0; i < N; i++) {
printf("%11.8g\n", *xd++);
}
printf("\n");
}
[3]
http://www.google.com/codesearch/p?hl=en#jVvm31OatEM/sundials/nvec_ser/
nvector_serial.c&q=nvector%2520sundials%2520cvode
_______________________________________________
Cython-dev mailing list
[email protected]
http://codespeak.net/mailman/listinfo/cython-dev