Неверный результат с islower при использовании ctypes

#python #c #ctypes

#python #c #ctypes

Вопрос:

 >>> from ctypes import *
>>> import ctypes.util
>>> libc = CDLL("libc.so.6")
>>> libc.printf("%cn", 104)
h
2
>>> libc.islower(104) # Works fine
512
>>> libc.islower.restype = c_bool # But when i do this...
>>> libc.islower(104)
False
>>> c_bool(512)
c_bool(True)
  

лично я думаю, что ‘h’ в нижнем регистре..

Это ошибка в ctypes, или я делаю что-то неправильно?

Комментарии:

1. В C любое ненулевое значение равно true. Таким образом, 512 является прекрасным показателем того, что h в нижнем регистре. Внутренне ctypes обычно реализуется в виде таблицы растровых изображений, по одному на символ. Здесь должен использоваться бит 9 для нижнего регистра.

2. @Gene Я думаю, он спрашивает о False последней команде.

3. о, действительно, но когда я заменяю возвращаемый тип на c_bool, он возвращает false

4. Вероятно, c_bool ошибочно объявлен как char, поэтому 2 ^ 9, принудительно преобразованные в c_bool, теряют 1 бит.

5. Предлагаю удалить тег C.

Ответ №1:

restype здесь не просто указать тип вывода Python, но, что наиболее важно, указать, какой тип C следует ожидать, и, следовательно, как его маршалировать. islower возвращает значение int , которое обычно имеет ширину 4 байта; если вы говорите, что оно возвращает значение bool (которое обычно составляет 1 байт), вы нарушаете ожидания кода маршалинга.

На этот раз вы получили неверный результат (вероятно, потому, что на вашей платформе код возврата отправляется в регистр, и поэтому он просто принимает младшие 8 бит), на другой платформе или для другого типа это может легко привести к поломке стека и, следовательно, к сбою вашего процесса.

Итак: не делайте этого. Всегда уважайте типы C API и конвертируйте после вызова.