forked from enthought/comtypes
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
3 changed files
with
107 additions
and
101 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
from ctypes import c_void_p | ||
import logging | ||
|
||
from comtypes._post_coinit.unknwn import _cominterface_meta | ||
|
||
|
||
logger = logging.getLogger(__name__) | ||
|
||
|
||
class _compointer_meta(type(c_void_p), _cominterface_meta): | ||
"metaclass for COM interface pointer classes" | ||
# no functionality, but needed to avoid a metaclass conflict | ||
|
||
|
||
class _compointer_base(c_void_p, metaclass=_compointer_meta): | ||
"base class for COM interface pointer classes" | ||
|
||
def __del__(self, _debug=logger.debug): | ||
"Release the COM refcount we own." | ||
if self: | ||
# comtypes calls CoUninitialize() when the atexit handlers | ||
# runs. CoUninitialize() cleans up the COM objects that | ||
# are still alive. Python COM pointers may still be | ||
# present but we can no longer call Release() on them - | ||
# this may give a protection fault. So we need the | ||
# _com_shutting_down flag. | ||
# | ||
if not type(self)._com_shutting_down: | ||
_debug("Release %s", self) | ||
self.Release() | ||
|
||
def __cmp__(self, other): | ||
"""Compare pointers to COM interfaces.""" | ||
# COM identity rule | ||
# | ||
# XXX To compare COM interface pointers, should we | ||
# automatically QueryInterface for IUnknown on both items, and | ||
# compare the pointer values? | ||
if not isinstance(other, _compointer_base): | ||
return 1 | ||
|
||
# get the value property of the c_void_p baseclass, this is the pointer value | ||
return cmp( | ||
super(_compointer_base, self).value, super(_compointer_base, other).value | ||
) | ||
|
||
def __eq__(self, other): | ||
if not isinstance(other, _compointer_base): | ||
return False | ||
# get the value property of the c_void_p baseclass, this is the pointer value | ||
return ( | ||
super(_compointer_base, self).value == super(_compointer_base, other).value | ||
) | ||
|
||
def __hash__(self): | ||
"""Return the hash value of the pointer.""" | ||
# hash the pointer values | ||
return hash(super(_compointer_base, self).value) | ||
|
||
# redefine the .value property; return the object itself. | ||
def __get_value(self): | ||
return self | ||
|
||
value = property(__get_value, doc="""Return self.""") | ||
|
||
def __repr__(self): | ||
ptr = super(_compointer_base, self).value | ||
return "<%s ptr=0x%x at %x>" % (self.__class__.__name__, ptr or 0, id(self)) | ||
|
||
# This fixes the problem when there are multiple python interface types | ||
# wrapping the same COM interface. This could happen because some interfaces | ||
# are contained in multiple typelibs. | ||
# | ||
# It also allows to pass a CoClass instance to an api | ||
# expecting a COM interface. | ||
@classmethod | ||
def from_param(cls, value): | ||
"""Convert 'value' into a COM pointer to the interface. | ||
This method accepts a COM pointer, or a CoClass instance | ||
which is QueryInterface()d.""" | ||
if value is None: | ||
return None | ||
# CLF: 2013-01-18 | ||
# A default value of 0, meaning null, can pass through to here. | ||
if value == 0: | ||
return None | ||
if isinstance(value, cls): | ||
return value | ||
# multiple python interface types for the same COM interface. | ||
# Do we need more checks here? | ||
if cls._iid_ == getattr(value, "_iid_", None): | ||
return value | ||
# Accept an CoClass instance which exposes the interface required. | ||
try: | ||
table = value._com_pointers_ | ||
except AttributeError: | ||
pass | ||
else: | ||
try: | ||
# a kind of QueryInterface | ||
return table[cls._iid_] | ||
except KeyError: | ||
raise TypeError("Interface %s not supported" % cls._iid_) | ||
return value.QueryInterface(cls.__com_interface__) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters