Mailing List Archive

extending questions
I have two questions, one simple, one a little bit whiny.

Firstly, I'm looking for a quick and easy way for a PyCFunction to
accept as an argument either an integer or a floating point number, so
that the function can be called as

func(1,1,1)

or as

func(0.5,0,2/3)

because python doesn't seem to let me consider an integer as a float.
I've tried using some of the conversion functions in the abstract
numeric suite and the PyFloat_GetDouble (or some similar name), but with
no luck - it always returned -1 for me. Any ideas?

Also, ust a suggestion, but would it be possible to add a
PyNumber_GetDouble(PyObject*n) function to the absract numberic
interface? This would be useful for this sort of situation.

My second question is, is there any work being done towards
updating/completing "Extending and Embedding" and "The Python C API" in
the standard documentation? As it is, the C API is just barely
useful.Wonderfully written, though. So can anyone offer a guess on when
peeking in the source will be mostly outmoded?

Anyways, thanks in advance for your help.
Jim Meier.
extending questions [ In reply to ]
Jim Meier <fatjim@home.com> wrote:
: I have two questions, one simple, one a little bit whiny.

: Firstly, I'm looking for a quick and easy way for a PyCFunction to
: accept as an argument either an integer or a floating point number, so
: that the function can be called as

: func(1,1,1)

: or as

: func(0.5,0,2/3)

: because python doesn't seem to let me consider an integer as a float.
: I've tried using some of the conversion functions in the abstract
: numeric suite and the PyFloat_GetDouble (or some similar name), but with
: no luck - it always returned -1 for me. Any ideas?

My best suggestion would be to use the PyInt_Check and PyFloat_check
functions.

PyObject *func(PyObject *self, PyObject *args)
{ PyObject *arg1, *arg2, *arg3;
double a1, a2, a3;

if (!PyArg_ParseTuple(args, "OOO", &arg1, &arg2, &arg3))
return NULL;
/* get the double from the first argument */
#define py_to_double(a, var) \
if (PyInt_Check(a)) (var) = (double)PyInt_AS_LONG(a); \
else if (PyFloat_Check(a)) (var) = PyFloat_AS_DOUBLE(a); \
else { PyErr_SetString(PyExc_TypeError, "must supply a number"); \
return NULL; }

py_to_double(arg1, a1);
py_to_double(arg2, a2);
py_to_double(arg3, a3);
#undef py_to_double

: Also, ust a suggestion, but would it be possible to add a
: PyNumber_GetDouble(PyObject*n) function to the absract numberic
: interface? This would be useful for this sort of situation.

There already is a PyNumber_Float(PyObject *) function; since the
purpose of the PyNumber_* functions is to make abstract numbers (classes,
builtins, etc.), you don't want to assume it is a double, but to
coerce it into a double.

PyObject *temp;
double result;

if ((temp = PyNumber_Float(number)) != NULL) {
result = PyFloat_AS_DOUBLE(temp);
Py_DECREF(temp);
} else
return NULL;

This is the same as "result = float(number)" in python, except that you
get the C result.

-Arcege
extending questions [ In reply to ]
"Michael P. Reilly" <arcege@shore.net> writes:

> Jim Meier <fatjim@home.com> wrote:
> : Firstly, I'm looking for a quick and easy way for a PyCFunction to
> : accept as an argument either an integer or a floating point number, so
> : that the function can be called as
>
> : func(1,1,1)
>
> : or as
>
> : func(0.5,0,2/3)
>
> : because python doesn't seem to let me consider an integer as a float.
> : I've tried using some of the conversion functions in the abstract
> : numeric suite and the PyFloat_GetDouble (or some similar name), but with
> : no luck - it always returned -1 for me. Any ideas?
>
> My best suggestion would be to use the PyInt_Check and PyFloat_check
> functions.
>
> PyObject *func(PyObject *self, PyObject *args)
> { PyObject *arg1, *arg2, *arg3;
> double a1, a2, a3;
>
> if (!PyArg_ParseTuple(args, "OOO", &arg1, &arg2, &arg3))
> return NULL;
> /* get the double from the first argument */
> #define py_to_double(a, var) \
> if (PyInt_Check(a)) (var) = (double)PyInt_AS_LONG(a); \
> else if (PyFloat_Check(a)) (var) = PyFloat_AS_DOUBLE(a); \
> else { PyErr_SetString(PyExc_TypeError, "must supply a number"); \
> return NULL; }
>
> py_to_double(arg1, a1);
> py_to_double(arg2, a2);
> py_to_double(arg3, a3);
> #undef py_to_double

Why not just

PyObject *
func(PyObject *self, PyObject *args)
{
double a1, a2, a3;

if (!PyArg_ParseTuple(args, "ddd", &a1, &a2, &a3))
return NULL;


/* ... */
}


This should work for Python floats, int and longs.


--
Bernhard Herzog | Sketch, a python based drawing program
herzog@online.de | http://www.online.de/home/sketch/