diff options
author | Pauli Virtanen <pav@iki.fi> | 2014-01-02 22:12:01 +0200 |
---|---|---|
committer | Pauli Virtanen <pav@iki.fi> | 2014-01-02 22:19:47 +0200 |
commit | 75c2d2fe3cc9daa6589707fb6b8512ffa48fc365 (patch) | |
tree | 32e729ca94dd28e06c7c2e10fd250f2ce4b91a2a /numpy/f2py/doc/fortranobject.tex | |
parent | a32807e61b25205cc08d552127234b56709c6242 (diff) | |
download | numpy-75c2d2fe3cc9daa6589707fb6b8512ffa48fc365.tar.gz |
DOC: move f2py documentation under doc/ and link its user guide with Sphinx
Diffstat (limited to 'numpy/f2py/doc/fortranobject.tex')
-rw-r--r-- | numpy/f2py/doc/fortranobject.tex | 574 |
1 files changed, 0 insertions, 574 deletions
diff --git a/numpy/f2py/doc/fortranobject.tex b/numpy/f2py/doc/fortranobject.tex deleted file mode 100644 index 88a56835e..000000000 --- a/numpy/f2py/doc/fortranobject.tex +++ /dev/null @@ -1,574 +0,0 @@ -\documentclass{article} - -\headsep=0pt -\topmargin=0pt -\headheight=0pt -\oddsidemargin=0pt -\textwidth=6.5in -\textheight=9in - -\usepackage{xspace} -\usepackage{verbatim} -\newcommand{\fpy}{\texttt{f2py}\xspace} -\newcommand{\bs}{\symbol{`\\}} -\newcommand{\email}[1]{\special{html:<A href="mailto:#1">}\texttt{<#1>}\special{html:</A>}} -\title{\texttt{PyFortranObject} --- example usages} -\author{ -\large Pearu Peterson\\ -\small \email{pearu@cens.ioc.ee} -} - -\begin{document} - -\maketitle - -\special{html: Other formats of this document: -<A href=pyfobj.ps.gz>Gzipped PS</A>, -<A href=pyfobj.pdf>PDF</A> -} - -\tableofcontents - -\section{Introduction} -\label{sec:intro} - -Fortran language defines the following concepts that we would like to -access from Python: functions, subroutines, data in \texttt{COMMON} blocks, -F90 module functions and subroutines, F90 module data (both static and -allocatable arrays). - -In the following we shall assume that we know the signatures (full -specifications of routine arguments and variables) of these concepts -from their Fortran source codes. Now, in order to call or use them -from C, one needs to have pointers to the corresponding objects. The -pointers to Fortran 77 objects (routines, data in \texttt{COMMON} -blocks) are readily available to C codes (there are various sources -available about mixing Fortran 77 and C codes). On the other hand, F90 -module specifications are highly compiler dependent and sometimes it -is not even possible to access F90 module objects from C (at least, -not directly, see remark about MIPSPro 7 Compilers). But using some -tricks (described below), the pointers to F90 module objects can be -determined in runtime providing a compiler independent solution. - -To use Fortran objects from Python in unified manner, \fpy introduces -\texttt{PyFortranObject} to hold pointers of the Fortran objects and -the corresponing wrapper functions. In fact, \texttt{PyFortranObject} -does much more: it generates documentation strings in run-time (for -items in \texttt{COMMON} blocks and data in F90 modules), provides -methods for accessing Fortran data and for calling Fortran routines, -etc. - -\section{\texttt{PyFortranObject}} -\label{sec:pyfortobj} - -\texttt{PyFortranObject} is defined as follows -\begin{verbatim} -typedef struct { - PyObject_HEAD - int len; /* Number of attributes */ - FortranDataDef *defs; /* An array of FortranDataDef's */ - PyObject *dict; /* Fortran object attribute dictionary */ -} PyFortranObject; -\end{verbatim} -where \texttt{FortranDataDef} is -\begin{verbatim} -typedef struct { - char *name; /* attribute (array||routine) name */ - int rank; /* array rank, 0 for scalar, max is F2PY_MAX_DIMS, - || rank=-1 for Fortran routine */ - struct {int d[F2PY_MAX_DIMS];} dims; /* dimensions of the array, || not used */ - int type; /* NPY_<type> || not used */ - char *data; /* pointer to array || Fortran routine */ - void (*func)(); /* initialization function for - allocatable arrays: - func(&rank,dims,set_ptr_func,name,len(name)) - || C/API wrapper for Fortran routine */ - char *doc; /* documentation string; only recommended - for routines. */ -} FortranDataDef; -\end{verbatim} -In the following we demonstrate typical usages of -\texttt{PyFortranObject}. Just relevant code fragments will be given. - - -\section{Fortran 77 subroutine} -\label{sec:f77subrout} - -Consider Fortran 77 subroutine -\begin{verbatim} -subroutine bar() -end -\end{verbatim} -The corresponding \texttt{PyFortranObject} is defined in C as follows: -\begin{verbatim} -static char doc_bar[] = "bar()"; -static PyObject *c_bar(PyObject *self, PyObject *args, - PyObject *keywds, void (*f2py_func)()) { - static char *capi_kwlist[] = {NULL}; - if (!PyArg_ParseTupleAndKeywords(args,keywds,"|:bar",capi_kwlist)) - return NULL; - (*f2py_func)(); - return Py_BuildValue(""); -} -extern void F_FUNC(bar,BAR)(); -static FortranDataDef f2py_routines_def[] = { - {"bar",-1, {-1}, 0, (char *)F_FUNC(bar,BAR),(void*)c_bar,doc_bar}, - {NULL} -}; -void initfoo() { - <snip> - d = PyModule_GetDict(m); - PyDict_SetItemString(d, f2py_routines_def[0].name, - PyFortranObject_NewAsAttr(&f2py_routines_def[0])); -} -\end{verbatim} -where CPP macro \texttt{F\_FUNC} defines how Fortran 77 routines are -seen in C. -In Python, Fortran subroutine \texttt{bar} is called as follows -\begin{verbatim} ->>> import foo ->>> foo.bar() -\end{verbatim} - -\section{Fortran 77 function} -\label{sec:f77func} -Consider Fortran 77 function -\begin{verbatim} -function bar() -complex bar -end -\end{verbatim} -The corresponding \texttt{PyFortranObject} is defined in C as in -previous example but with the following changes: -\begin{verbatim} -static char doc_bar[] = "bar = bar()"; -static PyObject *c_bar(PyObject *self, PyObject *args, - PyObject *keywds, void (*f2py_func)()) { - complex_float bar; - static char *capi_kwlist[] = {NULL}; - if (!PyArg_ParseTupleAndKeywords(args,keywds,"|:bar",capi_kwlist)) - return NULL; - (*f2py_func)(&bar); - return Py_BuildValue("O",pyobj_from_complex_float1(bar)); -} -extern void F_WRAPPEDFUNC(bar,BAR)(); -static FortranDataDef f2py_routines_def[] = { - {"bar",-1,{-1},0,(char *)F_WRAPPEDFUNC(bar,BAR),(void *)c_bar,doc_bar}, - {NULL} -}; -\end{verbatim} -where CPP macro \texttt{F\_WRAPPEDFUNC} gives the pointer to the following -Fortran 77 subroutine: -\begin{verbatim} -subroutine f2pywrapbar (barf2pywrap) -external bar -complex bar, barf2pywrap -barf2pywrap = bar() -end -\end{verbatim} -With these hooks, calling Fortran functions returning composed types -becomes platform/compiler independent. - - -\section{\texttt{COMMON} block data} -\label{sec:commondata} - -Consider Fortran 77 \texttt{COMMON} block -\begin{verbatim} -integer i -COMMON /bar/ i -\end{verbatim} -In order to access the variable \texttt{i} from Python, -\texttt{PyFortranObject} is defined as follows: -\begin{verbatim} -static FortranDataDef f2py_bar_def[] = { - {"i",0,{-1},NPY_INT}, - {NULL} -}; -static void f2py_setup_bar(char *i) { - f2py_bar_def[0].data = i; -} -extern void F_FUNC(f2pyinitbar,F2PYINITBAR)(); -static void f2py_init_bar() { - F_FUNC(f2pyinitbar,F2PYINITBAR)(f2py_setup_bar); -} -void initfoo() { - <snip> - PyDict_SetItemString(d, "bar", PyFortranObject_New(f2py_bar_def,f2py_init_bar)); -} -\end{verbatim} -where auxiliary Fortran function \texttt{f2pyinitbar} is defined as follows -\begin{verbatim} -subroutine f2pyinitbar(setupfunc) -external setupfunc -integer i -common /bar/ i -call setupfunc(i) -end -\end{verbatim} -and it is called in \texttt{PyFortranObject\_New}. - - -\section{Fortran 90 module subroutine} -\label{sec:f90modsubrout} - -Consider -\begin{verbatim} -module fun - subroutine bar() - end subroutine bar -end module fun -\end{verbatim} -\texttt{PyFortranObject} is defined as follows -\begin{verbatim} -static char doc_fun_bar[] = "fun.bar()"; -static PyObject *c_fun_bar(PyObject *self, PyObject *args, - PyObject *keywds, void (*f2py_func)()) { - static char *kwlist[] = {NULL}; - if (!PyArg_ParseTupleAndKeywords(args,keywds,"",kwlist)) - return NULL; - (*f2py_func)(); - return Py_BuildValue(""); -} -static FortranDataDef f2py_fun_def[] = { - {"bar",-1,{-1},0,NULL,(void *)c_fun_bar,doc_fun_bar}, - {NULL} -}; -static void f2py_setup_fun(char *bar) { - f2py_fun_def[0].data = bar; -} -extern void F_FUNC(f2pyinitfun,F2PYINITFUN)(); -static void f2py_init_fun() { - F_FUNC(f2pyinitfun,F2PYINITFUN)(f2py_setup_fun); -} -void initfoo () { - <snip> - PyDict_SetItemString(d, "fun", PyFortranObject_New(f2py_fun_def,f2py_init_fun)); -} -\end{verbatim} -where auxiliary Fortran function \texttt{f2pyinitfun} is defined as -follows -\begin{verbatim} -subroutine f2pyinitfun(f2pysetupfunc) -use fun -external f2pysetupfunc -call f2pysetupfunc(bar) -end subroutine f2pyinitfun -\end{verbatim} -The following Python session demonstrates how to call Fortran 90 -module function \texttt{bar}: -\begin{verbatim} ->>> import foo ->>> foo.fun.bar() -\end{verbatim} - -\section{Fortran 90 module function} -\label{sec:f90modfunc} - -Consider -\begin{verbatim} -module fun - function bar() - complex bar - end subroutine bar -end module fun -\end{verbatim} -\texttt{PyFortranObject} is defined as follows -\begin{verbatim} -static char doc_fun_bar[] = "bar = fun.bar()"; -static PyObject *c_fun_bar(PyObject *self, PyObject *args, - PyObject *keywds, void (*f2py_func)()) { - complex_float bar; - static char *kwlist[] = {NULL}; - if (!PyArg_ParseTupleAndKeywords(args,keywds,"",kwlist)) - return NULL; - (*f2py_func)(&bar); - return Py_BuildValue("O",pyobj_from_complex_float1(bar)); -} -static FortranDataDef f2py_fun_def[] = { - {"bar",-1,{-1},0,NULL,(void *)c_fun_bar,doc_fun_bar}, - {NULL} -}; -static void f2py_setup_fun(char *bar) { - f2py_fun_def[0].data = bar; -} -extern void F_FUNC(f2pyinitfun,F2PYINITFUN)(); -static void f2py_init_fun() { - F_FUNC(f2pyinitfun,F2PYINITFUN)(f2py_setup_fun); -} -void initfoo() { - <snip> - PyDict_SetItemString(d, "fun", PyFortranObject_New(f2py_fun_def,f2py_init_fun)); -} -\end{verbatim} -where -\begin{verbatim} -subroutine f2pywrap_fun_bar (barf2pywrap) -use fun -complex barf2pywrap -barf2pywrap = bar() -end - -subroutine f2pyinitfun(f2pysetupfunc) -external f2pysetupfunc,f2pywrap_fun_bar -call f2pysetupfunc(f2pywrap_fun_bar) -end -\end{verbatim} - - -\section{Fortran 90 module data} -\label{sec:f90moddata} - -Consider -\begin{verbatim} -module fun - integer i -end module fun -\end{verbatim} -Then -\begin{verbatim} -static FortranDataDef f2py_fun_def[] = { - {"i",0,{-1},NPY_INT}, - {NULL} -}; -static void f2py_setup_fun(char *i) { - f2py_fun_def[0].data = i; -} -extern void F_FUNC(f2pyinitfun,F2PYINITFUN)(); -static void f2py_init_fun() { - F_FUNC(f2pyinitfun,F2PYINITFUN)(f2py_setup_fun); -} -void initfoo () { - <snip> - PyDict_SetItemString(d, "fun", - PyFortranObject_New(f2py_fun_def,f2py_init_fun)); -} -\end{verbatim} -where -\begin{verbatim} -subroutine f2pyinitfun(f2pysetupfunc) -use fun -external f2pysetupfunc -call f2pysetupfunc(i) -end subroutine f2pyinitfun -\end{verbatim} -Example usage in Python: -\begin{verbatim} ->>> import foo ->>> foo.fun.i = 4 -\end{verbatim} - -\section{Fortran 90 module allocatable array} -\label{sec:f90modallocarr} - -Consider -\begin{verbatim} -module fun - real, allocatable :: r(:) -end module fun -\end{verbatim} -Then -\begin{verbatim} -static FortranDataDef f2py_fun_def[] = { - {"r",1,{-1},NPY_FLOAT}, - {NULL} -}; -static void f2py_setup_fun(void (*r)()) { - f2py_fun_def[0].func = r; -} -extern void F_FUNC(f2pyinitfun,F2PYINITFUN)(); -static void f2py_init_fun() { - F_FUNC(f2pyinitfun,F2PYINITFUN)(f2py_setup_fun); -} -void initfoo () { - <snip> - PyDict_SetItemString(d, "fun", PyFortranObject_New(f2py_fun_def,f2py_init_fun)); -} -\end{verbatim} -where -\begin{verbatim} -subroutine f2py_fun_getdims_r(r,s,f2pysetdata) -use fun, only: d => r -external f2pysetdata -logical ns -integer s(*),r,i,j -ns = .FALSE. -if (allocated(d)) then - do i=1,r - if ((size(d,r-i+1).ne.s(i)).and.(s(i).ge.0)) then - ns = .TRUE. - end if - end do - if (ns) then - deallocate(d) - end if -end if -if ((.not.allocated(d)).and.(s(1).ge.1)) then - allocate(d(s(1))) -end if -if (allocated(d)) then - do i=1,r - s(i) = size(d,r-i+1) - end do -end if -call f2pysetdata(d,allocated(d)) -end subroutine f2py_fun_getdims_r - -subroutine f2pyinitfun(f2pysetupfunc) -use fun -external f2pysetupfunc,f2py_fun_getdims_r -call f2pysetupfunc(f2py_fun_getdims_r) -end subroutine f2pyinitfun -\end{verbatim} -Usage in Python: -\begin{verbatim} ->>> import foo ->>> foo.fun.r = [1,2,3,4] -\end{verbatim} - -\section{Callback subroutine} -\label{sec:cbsubr} - -Thanks to Travis Oliphant for working out the basic idea of the -following callback mechanism. - -Consider -\begin{verbatim} -subroutine fun(bar) -external bar -call bar(1) -end -\end{verbatim} -Then -\begin{verbatim} -static char doc_foo8_fun[] = " -Function signature: - fun(bar,[bar_extra_args]) -Required arguments: - bar : call-back function -Optional arguments: - bar_extra_args := () input tuple -Call-back functions: - def bar(e_1_e): return - Required arguments: - e_1_e : input int"; -static PyObject *foo8_fun(PyObject *capi_self, PyObject *capi_args, - PyObject *capi_keywds, void (*f2py_func)()) { - PyObject *capi_buildvalue = NULL; - PyObject *bar_capi = Py_None; - PyTupleObject *bar_xa_capi = NULL; - PyTupleObject *bar_args_capi = NULL; - jmp_buf bar_jmpbuf; - int bar_jmpbuf_flag = 0; - int bar_nofargs_capi = 0; - static char *capi_kwlist[] = {"bar","bar_extra_args",NULL}; - - if (!PyArg_ParseTupleAndKeywords(capi_args,capi_keywds,\ - "O!|O!:foo8.fun",\ - capi_kwlist,&PyFunction_Type,&bar_capi,&PyTuple_Type,&bar_xa_capi)) - goto capi_fail; - - bar_nofargs_capi = cb_bar_in_fun__user__routines_nofargs; - if (create_cb_arglist(bar_capi,bar_xa_capi,1,0, - &cb_bar_in_fun__user__routines_nofargs,&bar_args_capi)) { - if ((PyErr_Occurred())==NULL) - PyErr_SetString(foo8_error,"failed in processing argument list for call-back bar." ); - goto capi_fail; - } - - SWAP(bar_capi,cb_bar_in_fun__user__routines_capi,PyObject); - SWAP(bar_args_capi,cb_bar_in_fun__user__routines_args_capi,PyTupleObject); - memcpy(&bar_jmpbuf,&cb_bar_in_fun__user__routines_jmpbuf,sizeof(jmp_buf)); - bar_jmpbuf_flag = 1; - - if ((setjmp(cb_bar_in_fun__user__routines_jmpbuf))) { - if ((PyErr_Occurred())==NULL) - PyErr_SetString(foo8_error,"Failure of a callback function"); - goto capi_fail; - } else - (*f2py_func)(cb_bar_in_fun__user__routines); - - capi_buildvalue = Py_BuildValue(""); -capi_fail: - - if (bar_jmpbuf_flag) { - cb_bar_in_fun__user__routines_capi = bar_capi; - Py_DECREF(cb_bar_in_fun__user__routines_args_capi); - cb_bar_in_fun__user__routines_args_capi = bar_args_capi; - cb_bar_in_fun__user__routines_nofargs = bar_nofargs_capi; - memcpy(&cb_bar_in_fun__user__routines_jmpbuf,&bar_jmpbuf,sizeof(jmp_buf)); - bar_jmpbuf_flag = 0; - } - return capi_buildvalue; -} -extern void F_FUNC(fun,FUN)(); -static FortranDataDef f2py_routine_defs[] = { - {"fun",-1,{-1},0,(char *)F_FUNC(fun,FUN),(void *)foo8_fun,doc_foo8_fun}, - {NULL} -}; -void initfoo8 () { - <snip> - PyDict_SetItemString(d, f2py_routine_defs[0].name, - PyFortranObject_NewAsAttr(&f2py_routine_defs[0])); -} -\end{verbatim} -where -\begin{verbatim} -PyObject *cb_bar_in_fun__user__routines_capi = Py_None; -PyTupleObject *cb_bar_in_fun__user__routines_args_capi = NULL; -int cb_bar_in_fun__user__routines_nofargs = 0; -jmp_buf cb_bar_in_fun__user__routines_jmpbuf; -static void cb_bar_in_fun__user__routines (int *e_1_e_cb_capi) { - PyTupleObject *capi_arglist = cb_bar_in_fun__user__routines_args_capi; - PyObject *capi_return = NULL; - PyObject *capi_tmp = NULL; - int capi_j,capi_i = 0; - - int e_1_e=(*e_1_e_cb_capi); - if (capi_arglist == NULL) - goto capi_fail; - if (cb_bar_in_fun__user__routines_nofargs>capi_i) - if (PyTuple_SetItem((PyObject *)capi_arglist,capi_i++,pyobj_from_int1(e_1_e))) - goto capi_fail; - - capi_return = PyEval_CallObject(cb_bar_in_fun__user__routines_capi, - (PyObject *)capi_arglist); - - if (capi_return == NULL) - goto capi_fail; - if (capi_return == Py_None) { - Py_DECREF(capi_return); - capi_return = Py_BuildValue("()"); - } - else if (!PyTuple_Check(capi_return)) { - capi_tmp = capi_return; - capi_return = Py_BuildValue("(O)",capi_tmp); - Py_DECREF(capi_tmp); - } - capi_j = PyTuple_Size(capi_return); - capi_i = 0; - goto capi_return_pt; -capi_fail: - fprintf(stderr,"Call-back cb_bar_in_fun__user__routines failed.\n"); - Py_XDECREF(capi_return); - longjmp(cb_bar_in_fun__user__routines_jmpbuf,-1); -capi_return_pt: - ; -} -\end{verbatim} -Usage in Python: -\begin{verbatim} ->>> import foo8 as foo ->>> def bar(i): print 'In bar i=',i -... ->>> foo.fun(bar) -In bar i= 1 -\end{verbatim} - -\end{document} - - -%%% Local Variables: -%%% mode: latex -%%% TeX-master: t -%%% End: |