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

Reply via email to