From: Mark Dickinson on
On Jul 16, 2:53 pm, kj <no.em...(a)please.post> wrote:
> This is extremely confusing.  From my naive reading of the
> documentation, I would have expected that the following two blocks
> would produce identical results (expl is one of the standard C math
> library exponential functions, with signature "long double expl(long
> double)"):
>
> MATH.expl.argtypes = [c_longdouble]
> MATH.expl.restype = c_longdouble
> print MATH.expl(0)
>
> MATH.expl.argtypes = [c_double]
> MATH.expl.restype = c_double
> print MATH.expl(0)
>
> ...but no, they don't: the first one prints out the correct result,
> 1.0, while the second one prints out 0.0, of all things.  (In fact,
> with the second (mis)configuration, the value returned by MATH.expl
> is always equal to its argument, go figure.)

This is just a case of garbage in, garbage out. In the second case
you're telling ctypes that the signature of expl is

double expl(double)

which just isn't true. ctypes has no way of telling that in fact expl
takes a long double rather than a double.

> I find these results perplexing because, based on the docs, I
> expected that they *both* would be analogous to doing the following
> in C:
>
> printf("%f\n", (double) expl((double) 0.0)); /* prints out 1.000000 */

No, not really. Assuming that expl has been declared somewhere (e.g.
you've included math.h), the C compiler knows that expl takes a long
double, so it'll convert the "(double) 0.0" argument to a long double
before passing it to expl.

Your second Python+ctypes example would be equivalent to doing
something like this in C:

#include <stdio.h>
double expl(double x); /* deliberate misdeclaration of expl */

int main(void) {
printf("%f\n", expl(0.0));
return 0;
}

which indeed produces 0.0 on my machine (gcc 4.2 / OS X 10.6). And
the compiler helpfully issues a warning:

test.c:1: warning: conflicting types for built-in function ‘expl’

Actually, the warning is a bit surprising, because there's only one
(wrong) declaration for expl, so what is there for it to conflict
with? The answer is that there are some commonly used library
functions that gcc has builtin versions for, so already knows the
signature of; expl is one of these. This is backed up by the fact
that when compiling with -fno-builtin-expl, no warning is issued.

> i.e., in *both* cases, expl would get passed a double (which gets
> automatically cast into a long double),

But how on earth would ctypes *know* it's supposed to convert
(nitpick: not cast) to a long double? The function signature isn't
available to ctypes; it's only through you setting .argtypes
and .restype that ctypes knows anything about it.

--
Mark
First  |  Prev  | 
Pages: 1 2
Prev: Identify the Color of an Image
Next: list.insert