Prev: Identify the Color of an Image
Next: list.insert
From: Mark Dickinson on 16 Jul 2010 10:56 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 |