You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
ORPA-pyOpenRPA/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/comtypes/util.py

97 lines
3.0 KiB

"""This module defines the funtions byref_at(cobj, offset)
and cast_field(struct, fieldname, fieldtype).
"""
from ctypes import *
def _calc_offset():
# Internal helper function that calculates where the object
# returned by a byref() call stores the pointer.
# The definition of PyCArgObject in C code (that is the type of
# object that a byref() call returns):
class PyCArgObject(Structure):
class value(Union):
_fields_ = [("c", c_char),
("h", c_short),
("i", c_int),
("l", c_long),
("q", c_longlong),
("d", c_double),
("f", c_float),
("p", c_void_p)]
#
# Thanks to Lenard Lindstrom for this tip:
# sizeof(PyObject_HEAD) is the same as object.__basicsize__.
#
_fields_ = [("PyObject_HEAD", c_byte * object.__basicsize__),
("pffi_type", c_void_p),
("tag", c_char),
("value", value),
("obj", c_void_p),
("size", c_int)]
_anonymous_ = ["value"]
# additional checks to make sure that everything works as expected
if sizeof(PyCArgObject) != type(byref(c_int())).__basicsize__:
raise RuntimeError("sizeof(PyCArgObject) invalid")
obj = c_int()
ref = byref(obj)
argobj = PyCArgObject.from_address(id(ref))
if argobj.obj != id(obj) or \
argobj.p != addressof(obj) or \
argobj.tag != 'P':
raise RuntimeError("PyCArgObject field definitions incorrect")
return PyCArgObject.p.offset # offset of the pointer field
################################################################
#
# byref_at
#
def byref_at(obj, offset,
_byref=byref,
_c_void_p_from_address = c_void_p.from_address,
_byref_pointer_offset = _calc_offset()
):
"""byref_at(cobj, offset) behaves similar this C code:
(((char *)&obj) + offset)
In other words, the returned 'pointer' points to the address of
'cobj' + 'offset'. 'offset' is in units of bytes.
"""
ref = _byref(obj)
# Change the pointer field in the created byref object by adding
# 'offset' to it:
_c_void_p_from_address(id(ref)
+ _byref_pointer_offset).value += offset
return ref
################################################################
#
# cast_field
#
def cast_field(struct, fieldname, fieldtype, offset=0,
_POINTER=POINTER,
_byref_at=byref_at,
_byref=byref,
_divmod=divmod,
_sizeof=sizeof,
):
"""cast_field(struct, fieldname, fieldtype)
Return the contents of a struct field as it it were of type
'fieldtype'.
"""
fieldoffset = getattr(type(struct), fieldname).offset
return cast(_byref_at(struct, fieldoffset),
_POINTER(fieldtype))[0]
__all__ = ["byref_at", "cast_field"]