Background: I'd like to compute second derivatives of a Python-implemented
function with the help of a Fortran library called NDL [1]. The function to be
differentiated can be implemented in C (an "external f" statement in the main
Fortran program will make available the functions in the "f.o" object file).
Now, I'm hoping to generate the requisite C code from a thin Cython wrapper
around my function, as in [2].
As a first step, I have declared a Cython function "cdef public", compiled it
(command-line output of compilation follows at the end), and am trying to call
it from C. However, the compilation fails at the line '#include "fun.h"' and I
don't understand why.
bash-3.2$ gcc usefun.c
In file included from usefun.c:2:
fun.h: In function 'DL_IMPORT':
fun.h:11: error: expected declaration specifiers before 'fun'
fun.h:15: error: expected declaration specifiers before 'PyMODINIT_FUNC'
In file included from /usr/include/stdio.h:34,
from usefun.c:3:
/usr/lib/gcc/x86_64-redhat-linux/4.1.2/include/stddef.h:214: error: storage
class specified for parameter 'size_t'
In file included from /usr/include/stdio.h:36,
from usefun.c:3:
/usr/include/bits/types.h:34: error: storage class specified for parameter
'__u_char'
/usr/include/bits/types.h:35: error: storage class specified for parameter
'__u_short'
[...etc etc]
/usr/include/stdio.h:821: error: expected ')' before '*' token
usefun.c:4: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{'
token
usefun.c:7: error: old-style parameter declarations in prototyped function
definition
fun.h:11: error: parameter name omitted
usefun.c:7: error: expected '{' at end of input
Any hints? I am a novice in the worlds of C and Fortran alike, so no
explanation is too basic 8-)
A couple of related questions/remarks:
* Assuming I get this to work, can the Fortran library call back to my Cython
function without having to re-initialize the Cython module for every callback?
* I see that there's an ongoing Fortran-to-Cython project that looks very
relevant [3]. If that could make the NDL Fortran library callable from Cython,
I'd be happy to provide a test case. (However, I only started coding Fortran
today, and the examples I've seen are in F77. Thus, the array handling issues
are a bit above my head. One-dimensional arrays of double will suffice for me.)
* The Fortran example (not shown, as I'm not quite there yet) links to an *.o
file produced by "gcc -c". I'm guessing that the *.o file that Cython puts in
the build/temp.linux-x86_64-2.5/ directory could be used in the same way?
Thank you in advance for any help.
Jon Olav Vik
== fun.pyx ==
"""
Cython function that can be called from C, and hopefully Fortran.
Compile with "python cysetup.py fun", see below.
"""
from math import *
print "This is a Cython module" # time-consuming initialization goes here
cdef public double fun(double *x, int n):
return x[0]*cos(x[1])+x[1]*cos(x[0])
== usefun.c ==
/* compile with "gcc usefun.c" */
#include "fun.h" // note to self: "" not <>
#include <stdio.h>
int main() {
double x[2] = {1.0, 1.1}; // initialize array
printf("fun(x) = %4.2f", fun(&x, 2)); // call include'd function
}
== cysetup.py ==
"""
Compile Cython file with distutils.setup()
This is just a hack to save me from having to write separate setup.py files
"""
from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext
import numpy as np
from sys import argv
import os
modulename = argv.pop(1)
for filename in modulename + ".c", modulename + ".so", "build":
try:
os.remove(filename)
except OSError:
pass
argv += ["build_ext", "--inplace"]
setup(
cmdclass = {'build_ext': build_ext},
ext_modules = [
Extension(modulename,
[modulename + ".pyx"],
include_dirs=['/usit/titan/u1/jonvi/usr/include', np.get_include
()],
library_dirs=['/usit/titan/u1/jonvi/usr/lib'],
# include_dirs=['/site/VERSIONS/sundials-2.3.0/include',
np.get_include ()],
# library_dirs=['/site/VERSIONS/sundials-2.3.0/lib'],
libraries=['sundials_cvode', 'sundials_nvecserial'],
# extra_compile_args=["-g"], extra_link_args=["-g"],
),
]
)
__import__(modulename)
== Compiling the Cython module ==
bash-3.2$ python cysetup.py fun
running build_ext
cythoning fun.pyx to fun.c
building 'fun' extension
gcc -pthread -fno-strict-aliasing -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-
prototypes -fPIC -I/usit/titan/u1/jonvi/usr/include -I/site/VERSIONS/
compython-2.5/Linux/lib/python2.5/site-packages/numpy/core/include -I/site/
VERSIONS/compython-2.5/Linux/include/python2.5 -c fun.c -o build/temp.linux-
x86_64-2.5/fun.o
gcc -pthread -shared build/temp.linux-x86_64-2.5/fun.o -L/usit/titan/u1/jonvi/
usr/lib -L/site/VERSIONS/compython-2.5/Linux/lib -lsundials_cvode -
lsundials_nvecserial -lpython2.5 -o fun.so
This is a Cython module
== Testing that it works on its own ==
bash-3.2$ python -c "import fun"
This is a Cython module
[1] C. Voglis et al., A numerical differentiation library exploiting
parallel architectures, Computer Physics Communications (2009),
doi:10.1016/j.cpc.2009.02.004
http://www.cs.uoi.gr/~voglis/
[2] http://docs.cython.org/docs/external_C_code.html#using-cython-declarations-
from-c
[3] http://wiki.cython.org/enhancements/fortran and links therein
_______________________________________________
Cython-dev mailing list
[email protected]
http://codespeak.net/mailman/listinfo/cython-dev