ctypes中使用WindowFromPoint
ctypes是一大利器,为Python调用c库函数、dll使用等提供了极大的便利。 但是使用ctypes下的函数遇到一些复杂的数据类型传参时怎么使用对接的数据类型呢。 很简单的比如使用ctypes.windll.user32.WindowFromPoint(POINT)函数。这个POINT类型Python中是没有的,而且ctypes下没有此类型。如何传参调用呢。
经过查阅官方文档,终于找到了最终解决方案。
直接使用报错如下
ctypes.ArgumentError: argument
1: <class
'TypeError'>: Don
't know how
to convert parameter
1
解决方案
import ctypes
class POINT(ctypes
.Structure):
_fields_ = [(
"x", ctypes
.c_int),
(
"y", ctypes
.c_int)]
op = ctypes
.windll.user32
print(op
.WindowFromPoint(POINT(
30,
40)))
官方文档说明
16.16.2.8. Structured data types
class ctypes.Union(*args, **kw)
Abstract base class
for unions
in native
byte order.
class ctypes.BigEndianStructure(*args, **kw)
Abstract base class
for structures
in big endian
byte order.
class ctypes.LittleEndianStructure(*args, **kw)
Abstract base class
for structures
in little endian
byte order.
Structures
with non-native
byte order cannot contain pointer type fields,
or any other data types containing pointer type fields.
class ctypes.Structure(*args, **kw)
Abstract base class
for structures
in native
byte order.
Concrete structure
and union types must be created
by subclassing
one of these types,
and at least define
a _fields_ class
variable. ctypes will
create descriptors which allow reading
and writing
the fields
by direct attribute accesses. These are
the
_fields_
A sequence defining
the structure fields. The
items must be
2-tuples
or 3-tuples. The
first item is
the name
of the field,
the second item specifies
the type
of the field;
it can be
any ctypes data type.
For
integer type fields like c_int,
a third optional
item can be given. It must be
a small positive
integer defining
the bit width
of the field.
Field names must be unique
within one structure
or union. This is
not checked, only
one field can be accessed when names are repeated.
It is possible
to define
the _fields_ class
variable after the class statement that defines
the Structure subclass, this allows creating data types that directly
or indirectly reference themselves:
class List(Structure):
pass
List.
_fields_ = [(
"pnext", POINTER(List)),
...
]
The
_fields_ class
variable must, however, be defined
before the type is
first used (
an instance is created, sizeof() is called
on it, and so on). Later assignments to the _fields_ class variable will raise an AttributeError.
It is possible
to defined sub-subclasses
of structure types, they inherit
the fields
of the base class plus
the _fields_ defined
in the sub-subclass,
if any.
_pack_
An optional small
integer that allows overriding
the alignment
of structure fields
in the instance.
_pack_ must already be defined when
_fields_ is assigned, otherwise
it will have no effect.
_anonymous_
An optional sequence that lists
the names
of unnamed (anonymous) fields.
_anonymous_ must be already defined when
_fields_ is assigned, otherwise
it will have no effect.
The fields listed
in this
variable must be structure
or union type fields. ctypes will
create descriptors
in the structure type that allows accessing
the nested fields directly,
without the need
to create the structure
or union field.
Here is
an example type (Windows):
class _U(Union):
_fields_ = [(
"lptdesc", POINTER(TYPEDESC)),
(
"lpadesc", POINTER(ARRAYDESC)),
(
"hreftype", HREFTYPE)]
class TYPEDESC(Structure):
_anonymous_ = (
"u",)
_fields_ = [(
"u", _U),
(
"vt", VARTYPE)]
The TYPEDESC structure describes
a COM data type,
the vt field specifies which
one of the union fields is valid. Since
the u field is defined
as anonymous field,
it is now possible
to access
the members directly off
the TYPEDESC instance. td.lptdesc
and td.u.lptdesc are equivalent, but
the former is faster since
it does
not need
to create a temporary
union instance:
td = TYPEDESC()
td.vt = VT_PTR
td.lptdesc = POINTER(some_type)
td.u.lptdesc = POINTER(some_type)
It is possible
to defined sub-subclasses
of structures, they inherit
the fields
of the base class. If
the subclass definition has
a separate
_fields_
variable,
the fields specified
in this are appended
to the fields
of the base class.
Structure
and union constructors accept both positional
and keyword arguments. Positional arguments are used
to initialize member fields
in the same order
as they are appear
in _fields_. Keyword arguments
in the constructor are interpreted
as attribute assignments, so they will initialize
_fields_
with the same name,
or create new attributes
for names
not present
in _fields_.
转载请注明原文地址: https://ju.6miu.com/read-6319.html