This issue tracker
has been migrated to
GitHub
,
and is currently
read-only
.
For more information,
see the GitHub FAQs in the Python's Developer Guide.
When dealing with a Structure containing c_char variables, the variables are incorrectly being typed as bytes. As a result, a pointer to those c_char variables can not be created because bytes is not a ctypes type.
from ctypes import (
Structure,
c_char,
pointer,
class MyStruct(Structure):
_fields_ = [("a", c_char), ("b", c_char), ("c", c_char)]
x: MyStruct = MyStruct(98, 99, 100)
print(type(x.a))
# Prints <class 'bytes'> ??? Both mypy and PyRight agree that x.a is a c_char.
some_variable = pointer(x.a)
# Traceback (most recent call last):
# File "C:\Users\cires\ctypes_test.py", line 23, in <module>
# some_variable = pointer(x.a)
# TypeError: _type_ must have storage info
A simple ctypes type implements a get function that's called when its value is returned as an attribute of struct/union, index of an array/pointer, or result of a function pointer. For example:
>>> a = (ctypes.c_char * 1)(97)
>>> p = ctypes.POINTER(ctypes.c_char)(a)
This behavior can't be changed. However, using a subclass of c_char works around it. For example:
>>> class my_char(ctypes.c_char): pass
>>> a = (my_char * 1)(97)
<my_char object at 0x7f007dadf640>
>>> a[0].value
>>> p = ctypes.POINTER(my_char)(a)
<my_char object at 0x7f007dadf6c0>
>>> p[0].value
Wow. Thank you Eryk Sun. While that seems like a convoluted way to make a type act like the type it is...it works. Verified it with the following code:
from ctypes import POINTER, c_char, sizeof, Structure
class char_from_c(c_char):
print("Size of c_char vs size of char_from_c:")
print(sizeof(c_char))
print(sizeof(char_from_c))
class my_structure(Structure):
_fields_ = [
("first_char", char_from_c),
("second_char", char_from_c),
("third_char", char_from_c),
my_structure_object: my_structure = my_structure(97, 98, 99)
pointer_to_char_from_c_in_my_structure = POINTER(c_char)(my_structure_object.first_char)
print("\nContents of pointer_to_char_from_c_in_my_structure:")
print(pointer_to_char_from_c_in_my_structure.contents)
print("\npointer_to_char_from_c_in_my_Structure[0]:")
print(pointer_to_char_from_c_in_my_structure[0])
print("\nValues from my_structure_object:")
character_counter = 0
while character_counter < sizeof(my_structure_object):
print(pointer_to_char_from_c_in_my_structure[character_counter])
character_counter += 1
...which gave me the following results:
Size of c_char vs size of char_from_c:
Contents of pointer_to_char_from_c_in_my_structure:
c_char(b'a')
pointer_to_char_from_c_in_my_Structure[0]:
Values from my_structure_object:
Again...Thank you. Closing this "bug" as it is weird...but not a bug.
2022-04-11 14:59:50adminsetgithub: 89448
2021-09-25 18:53:23ciresnavesetstatus: open -> closed
resolution: not a bug
messages:
+ msg402642
stage: resolved
2021-09-24 20:19:04eryksunsetnosy:
+ eryksun
messages:
+ msg402585
2021-09-24 19:23:45ciresnavecreate