Python и ctypes: почему printf ("% f", 10.1) неправильный - PullRequest
3 голосов
/ 16 ноября 2011

У меня есть вопрос о ctypes в Python

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 ]

4 голосов
/ 16 ноября 2011

Согласно документации ctypes :

Нет, целые, длинные, байтовые и юникодные строки являются единственными нативные объекты Python, которые могут непосредственно использоваться в качестве параметров в этих вызовы функций. Ни один не передается как указатель C NULL, байтовые строки и Строки Unicode передаются как указатель на блок памяти, который содержит их данные (char * или wchar_t *). Python целые и Python long передаются как тип C int по умолчанию для платформ, их значение замаскированы под тип C.

Итак, вам не нужно использовать c_int или c_string, потому что это "нативные" объекты Python.

Для вашей второй проблемы Википедия говорит :

f, F: двойное в нормальном (с фиксированной запятой) обозначении. «F» и «F» отличается только в том, как печатаются строки для бесконечного числа или NaN ('inf', «бесконечность» и «nan» для «f», «INF», «INFINITY» и «NAN» для «F»).

MSDN также сообщает , что модификатор "f" предназначен для типа double.

Итак, похоже, что python-ctypes читают одну и ту же документацию и считают, что с% f вы должны дать двойное число.

2 голосов
/ 16 ноября 2011

Попробуйте printf("%f", c_double(10.1))

Объяснение: printf() - это функция varargs.Параметры формата объясняют, какой тип вы можете ожидать в стеке.

Проблема: нет способа различить аргументы float и double при просмотре формата, но float использует 4 байта, в то время какdouble использует 8. Так как printf() может определить, какой из них был помещен в стек кодом?

Ответ: float s всегда преобразуются в double.Таким образом, все типы с плавающей запятой всегда используют одинаковое количество байтов в стеке, и printf() может определить их адрес.

...