writing a generic method

F

fj

I am new in Python programming. I try to connect to Python various
libraries written either in C of in Fortran. The job is not really hard
but I meet a trouble when trying to build up a generic routine like in
C++ or F90, i.e. a single routine name for various uses.

Here is an example with a Fortran 77 library:

static PyObject* mdb_get(PyObject *self, PyObject *args){
const char *cname,*cprop;
int lname,lprop;
double x,z;
int ix;
if(PyArg_ParseTuple(args,"s#s#d",&cname,&lname,&cprop,&lprop,&x))
mdbgetd_(cname,cprop,&x,&z,lname,lprop);
else
if(PyArg_ParseTuple(args,"s#s#i",&cname,&lname,&cprop,&lprop,&ix))
mdbgeti_(cname,cprop,&ix,&z,lname,lprop);
else
return NULL;
return Py_BuildValue("d",z);
}

This method should be used as a single Python function mdb::get. It
should have two possible forms:
mdb.get("H2O","h_l(T)",300.)
mdb.get("H2O","atom",2)

As you see, the third argument should be either a real or an integer.
Unfortunately, the result depends on the order of instructions because
Python automatically converts
integer into real and vice versa. For instance, the intructions above
are interpreted as follows :
mdb.get("H2O","h_t(T)",300.) (correct)
mdb.get("H2O","atom",2.) (wrong because 2 and 2. are not
equivalent in my case)

So my question is : Is it possible to deactivate this automatic
conversion ?
Presently, the only solution I found was to write two functions
(mdb.getr and mdb.geti)
 
J

jepler

You could use a format like "#s#sO", and then use PyFloat_Check,
PyFloat_AsDouble, and the equivalent PyInt macros to get the "C" value out of
the Python object.

You should be able to use the converter "O&" to get what you want. The
conversion function might look like:
int double_only(PyObject *o, double *d) {
if(!PyFloat_Check(o)) return 0;
*d = PyFloat_AsDouble(o);
}
and the call would be
if(PyArg_ParseTuple(args,"s#s#O&",&cname,&lname,&cprop,&lprop,double_only,&x))
mdbgetd_(cname,cprop,&x,&z,lname,lprop);
(untested)

I believe that if you write
if(PyArg_ParseTuple(...))
else(PyArg_ParseTuple(...))
you're missing a PyErr_Clear() before the second PyArg_ParseTuple(). Returning
non-NULL when an exception has been set in C code will lead to a hard-to-trace
failure down the road.

Jeff

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.1 (GNU/Linux)

iD8DBQFDgd3kJd01MZaTXX0RAhbeAJ94PU1Bdy9DWWETl5RnU05fZ3Ou8gCfUHUi
xPs12YMa3Zk3HoT+UCv1GHo=
=UiDM
-----END PGP SIGNATURE-----
 
F

fj

Nice !

Thank you very much : it works well with "s#s#O"

And also thank you for your advice to insert PyErr_Clear() when several
calls to PyArgParseTuple are performed in the same method.

bye

FJ
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top