相关文章推荐

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
 
推荐文章