首页 > 解决方案 > ctypes 对函数中可变参数的奇怪处理

问题描述

我正在启动这个片段:

>>> 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期望一个doublefor%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 位机器。

标签: pythoncprintfctypes

解决方案


调用者负责从floatto进行类型提升double。但是除非你告诉它,否则ctypes对签名一无所知。printf它不知道它是可变参数并且需要类型提升。

如果您不通过设置and来判断ctypes函数的签名是什么,它会假定返回类型,并且您传入的任何参数都与签名匹配。所以在你的情况下,它只是假设签名是:argtypesrestypeintprintf

int printf(char*, double, float)

据我所知,没有办法在 中定义可变参数argtypesctypes但它似乎并没有进行强制转换,即使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

推荐阅读