writing a generic method

Discussion in 'Python' started by fj, Nov 21, 2005.

  1. fj

    fj Guest

    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)
    fj, Nov 21, 2005
    #1
    1. Advertising

  2. fj

    Guest

    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-----
    , Nov 21, 2005
    #2
    1. Advertising

  3. fj

    fj Guest

    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
    fj, Nov 21, 2005
    #3
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Murat Tasan
    Replies:
    1
    Views:
    8,027
    Chaitanya
    Feb 3, 2009
  2. Replies:
    5
    Views:
    2,311
    Thomas Hawtin
    Sep 12, 2005
  3. Replies:
    1
    Views:
    365
    Chris Smith
    Apr 19, 2006
  4. Replies:
    2
    Views:
    423
  5. minlearn
    Replies:
    2
    Views:
    445
    red floyd
    Mar 13, 2009
Loading...

Share This Page