ctypes 奇怪地处理函数中的可变参数
ctypes weird handling of variadic arguments in functions
我正在启动这个片段:
>>> 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
期望 double
为 %f
但我认为浮点数在可变参数函数中被提升为双精度数,如下面的 C 代码所示:
#include<stdio.h>
int main()
{
float a = 1.0f;
double b = 1.0;
printf("%f %f\n", a, b);
}
产生预期的 1.000000 1.000000
.
我错过了什么吗?编译器是否在 C 代码中进行了一些隐式转换?
我使用的是 64 位机器。
调用者负责将类型从 float
提升到 double
。但是 ctypes
对 printf
的签名一无所知,除非你告诉它。它不知道它是可变的并且需要类型提升。
如果您不通过设置 argtypes
和 restype
来告诉 ctypes
函数的签名是什么,它会假定 int
return类型,并且您传入的任何参数都与签名匹配。因此,在您的情况下,它只是假设 printf
的签名是:
int printf(char*, double, float)
据我所知,无法在 ctypes
中定义可变参数 argtypes
,但即使设置了 argtypes
,它似乎也不会进行转换:
>>> 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
我正在启动这个片段:
>>> 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
期望 double
为 %f
但我认为浮点数在可变参数函数中被提升为双精度数,如下面的 C 代码所示:
#include<stdio.h>
int main()
{
float a = 1.0f;
double b = 1.0;
printf("%f %f\n", a, b);
}
产生预期的 1.000000 1.000000
.
我错过了什么吗?编译器是否在 C 代码中进行了一些隐式转换?
我使用的是 64 位机器。
调用者负责将类型从 float
提升到 double
。但是 ctypes
对 printf
的签名一无所知,除非你告诉它。它不知道它是可变的并且需要类型提升。
如果您不通过设置 argtypes
和 restype
来告诉 ctypes
函数的签名是什么,它会假定 int
return类型,并且您传入的任何参数都与签名匹配。因此,在您的情况下,它只是假设 printf
的签名是:
int printf(char*, double, float)
据我所知,无法在 ctypes
中定义可变参数 argtypes
,但即使设置了 argtypes
,它似乎也不会进行转换:
>>> 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