Как ctypes могут определять типы переданных целых чисел? - PullRequest
1 голос
/ 23 октября 2019

Я взаимодействую с этим кодом C:

extern "C" void print_int(short a, int b, long c, long long d)
{
   printf("%hi %i %li %lli", a, b, c, d);
}

с этим кодом Python:

from ctypes import *
lib=cdll.LoadLibrary("./libtest.so")
lib.print_int(1,2,3,4)

Даже если я не приведу аргументы в коде print_int, онипрошло правильно, и я получаю:

1 2 3 4

, как и ожидалось. Почему ctypes не могут создавать одинаковые числа с плавающей запятой? Следующий фрагмент:

extern "C" void print_float(float a, double b, long double c)
{
   printf("%f %lf %Lf", a, b, c);
}

потребует явного приведения из ctypes в противном случае возникает исключение.

lib.print_float(c_float(1.0), c_double(2.0), c_longdouble(3.0))

Я работаю в Unix, компилирую с cdecl соглашение о вызовах, если это имеет значение.

1 Ответ

2 голосов
/ 23 октября 2019

Потому что по умолчанию и размер стека. Если вы не укажете тип, ctypes предполагает c_int. В 64-битной системе стек является 64-битным, поэтому шорты, целые, длинные, длинные длинные все являются знаковыми расширениями и используют 64-битный слот стека. long long сломался бы в 32-битной системе. float - это совершенно другой двоичный формат, который не совместим с c_int.

. Вы можете использовать .argtypes для указания типов параметров и затем передавать значения в обычном режиме. Также .restype указывает возвращаемое значение:

lib.print_float.argtypes = c_float,c_double,c_longdouble
lib.print_float.restype = None
lib.print_float(1,2,3)
...