Python和ctypes:为什么printf("%f",10.1)是错误的

时间:2011-11-16 11:05:48

标签: python printf ctypes

我对python中的ctypes有疑问

from ctypes import *
printf = cdll.msvcrt.printf
printf("%s\n", "Hello World!")
printf("%d\n", 100)
printf("%f\n", 10.1)

结果:

Hello World!
100
Traceback (most recent call last):
  File "C:\Users\Windows7\Desktop\test.py", line 5, in <module>
    printf("%f\n", 10.1)
ctypes.ArgumentError: argument 2: <type 'exceptions.TypeError'>: Don't know how to convert parameter 2

我知道如何纠正错误:10.1应该被c_double(10.1)替换,但为什么我应该在这里使用c_double()函数?前两个printf根本不需要c_string()c_int()

而且,它是“%f”,而不是“%lf”,所以我想如果我必须在这里使用ctypes函数,我应该使用c_float()而不是c_double,但是当我尝试printf("%f", c_float(10.1))时,我得到了错误的结果:0.000000,为什么?

2 个答案:

答案 0 :(得分:4)

根据ctypes documentation

  

无,整数,长整数,字节字符串和unicode字符串是唯一的   可以直接用作这些参数的本机Python对象   函数调用。 None作为C NULL指针传递,字节串和   unicode字符串作为指向内存块的指针传递   包含他们的数据(char *或wchar_t *)。 Python整数和Python   long作为平台默认的C int类型传递,它们的值是   蒙面以适应C型。

因此,您不需要使用c_int或c_string,因为它们是“本机”python对象。

对于您的第二个问题,Wikipedia says

  

f,F:正常(定点)表示法加倍。 'f'和'F'只是不同   如何打印无限数字或NaN的字符串('inf',   'inf'和'nan'代表'f','INF','INFINITY'和'NAN'代表'F')。

MSDN says“f”修饰符也是双重类型。

因此,看起来python-ctypes读取相同的文档,并考虑使用%f,你必须给出一个双倍。

答案 1 :(得分:2)

尝试printf("%f", c_double(10.1))

说明:printf()是一个varargs函数。格式参数说明了堆栈中可以预期的类型。

问题:在查看格式时无法区分floatdouble参数,float使用4个字节而double使用8。所以如何可以printf()告诉哪一个被代码推到了堆栈上?

答案:float始终转换为double。这样,所有浮点类型总是在堆栈上使用相同的字节数,printf()可以找出它们的地址。