Reputation: 402
I am launching this snippet:
>>> from ctypes import *
>>> libc = CDLL("libc.so.6")
>>> libc.printf("%f %f\n", c_float(1.0), c_double(1.0))
0.000000 1.000000
printf
expects a double
for %f
BUT I thought floats got promoted to doubles in variadic functions, as the following C code shows:
#include<stdio.h>
int main()
{
float a = 1.0f;
double b = 1.0;
printf("%f %f\n", a, b);
}
produces the expected 1.000000 1.000000
.
Am I missing something? Is the compiler doing some implicit casting in the C code?
I am using a 64-bits machine.
Upvotes: 3
Views: 508
Reputation: 544
The caller is responsible for doing the type promotion from float
to double
. But ctypes
doesn't know anything about the signature of printf
unless you tell it. It doesn't know it's variadic and that type promotion is required.
If you don't tell ctypes
what the signature of a function is by setting argtypes
and restype
, it assumes a int
return type, and that whatever parameter you passed in match the signatures. So in your case it just assumes the signature of printf
is:
int printf(char*, double, float)
As far as I know there is no way to define a variadic argtypes
in ctypes
, but it doesn't seem to do casting anyway, even if argtypes
is set:
>>> from ctypes import *
>>> libc = CDLL("libc.so.6")
>>> libc.printf.argtypes = [c_char_p, c_double, c_double]
>>> libc.printf(c_char_p(b"%f %f\n"), c_double(1.0), c_float(1.0))
Traceback (most recent call last):
File "printf.py", line 5, in <module>
libc.printf(c_char_p(b"%f %f\n"), c_double(1.0), c_float(1.0))
ctypes.ArgumentError: argument 3: <class 'TypeError'>: wrong type
Upvotes: 1