The ctypes COM framework
"overview":index.html :: "tutorial":tutorial.html ::
"reference":reference.html :: "faq":faq.html
( Work in progress: COM :: "COM sample":sum_sample.html )
**Warning: work in progress**
On Windows, the 'ctypes' distribution contains a simple COM
framework. This document is a short reference to the modules
contained in the 'ctypes.com' package.
The 'ctypes.com' module
'GUID'
Instances of this type represent a global unique identifier
'guid' used everywhere by COM. 'GUID' is a subclass of
'ctypes.Structure'.
'HRESULT(value)'
A *function* to be used as restype for COM interface methods.
It returns the value passed to it, or automatically raises a
WindowsError with a description if the integer value
represents an error code.
'STDMETHOD(restype, name, *argtypes)'
This is a helper function to define COM interface methods. It
returns nothing interesting, except that the return value are
used by the *interface metaclass* to construct the interface
vtable.
'restype' is the result type of the COM method, typically
'HRESULT', but you can also use other ctypes types. 'name' is
the name of the COM method. 'argtypes' is a sequence of
argument types this method requires, these must be ctypes
types like 'c_int', 'POINTER(GUID)' or whatever.
'IUnknown'
This is the base class for all COM interfaces. Subclasses
must have a '_methods_' attribute, which is a list of all COM
interface methods used in this interface in vtable order. The
'_methods_' attribute for derived classes must include the
methods of the base class.
It is not necessary to define the '_methods_' attribute in the
class definition statement, it can also be assigned later. But
it must be set the first time the interface class is used.
Subclasses must also have an '_iid_' attribute, which must be
a 'GUID' instance, and which is the global unique identifier
for this interface.
Here a is sample interface definition::
class IPersist(IUnknown):
_iid_ = GUID("{0000010C-0000-0000-C000-000000000046}")
_methods_ = IUnknown._methods_ + [
STDMETHOD(HRESULT, "GetClassID", POINTER(GUID))
]
These interface definitions are used to *implement* COM
interfaces, or to *use* COM interfaces. In client code, if you
are using the interface, an instance of the interface class is
created and you can call methods on it, in server code the
interface class provides information to the metaclass so that
the interface vtable can be created.
Note that 'ctypes.com' contains a tool named 'readtlb' which
creates Python wrapper modules from type libraries ('.tlb'
files). In addition to interface subclasses these modules
also contain information about the type library itself, the
coclasses, structure, unions, and enums contained in the type
libraries.
The 'CreateInstance' function (see below), if successful,
returns a pointer to an interface.
These interface pointers have instance methods dynamically
created by the metaclass for all methods defined in the COM
interface, which directly call the underlying C vtable
method. 'IUnknown', for example, has 'QueryInterface',
'AddRef', and 'Release' methods.
Although the COM reference counting is mostly handled
automatically by the framework, and you don't need to call
'AddRef' and 'Release' yourself, it may be useful in debugging
- they return the COM reference count of the interface after
incrementing or decrementing it.
'QueryInterface' is useful for client side COM programming, it
requires a pointer to a 'GUID' instance and a pointer to a
pointer to an interface instance, so a typical call would be::
# assuming iunk is a valid pointer to an IUnknown interface...
# create an empty pointer to a dispatch interface instance
from ctypes.com.automation import IDispatch
idisp = POINTER(IDispatch)() # XXX explain
# ask the object for a dispatch interface
iunk.QueryInterface(byref(IDispatch._iid_), byref(idisp))
This code will request an IDispatch interface pointer and
store it in 'idisp', or raise an exception if the object
doesn't support the IDispatch interface. If the call is
successful, you can for example call the 'GetTypeInfoCount'
method to see if this object exposes type information::
count = c_uint()
idisp.GetTypeInfoCount(byref(count))
print count.value
'CreateInstance(coclass [,interface [,clsctx]])'
Calls the 'CoCreateInstance' api to create a COM
object, and returns a COM interface pointer.
'coclass' must have a '_reg_clsid_' attribute which is a
string representation of a *guid*. If 'interface' is not
specified, the default COM interface which is the first item
in the '_com_interfaces_' attribute of 'coclass' is
used. 'clsctx' can be used to specify the context in which the
object is run, if not specified,
'CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER' is used.
'COMObject'
This is an abstract base class used to implement COM objects.
Concrete subclasses must provide a '_com_interfaces_' class
attribute, which must be a list containing interfaces this
object implements. The interfaces must be subclasses of
'IUnknown'.
The 'COMObject' class contains the implementation of the
'IUnknown' interface, you must implement other interfaces
yourself by providing the interface method in the subclass.
The 'ctypes.com.automation' module
This module contains automation interfaces, data types and
functions.
The 'ctypes.com.server' module
This module contains additional functions and interfaces to
implement COM servers.
The 'ctypes.com.register' module
This module contains functions to register and unregister COM servers
with the Windows registry.
The 'ctypes.com.connectionpoints' module
This module contains the connectionpoint interfaces definitions,
and support code to receive events from COM objects.
The 'ctypes.com.ole' module
This module contains some ole interfaces.
The 'ctypes.com.persist' module
This module contains persist interfaces.
The 'ctypes.com.w_getopt' module
XXX The code in this module will probably be moved into a
'ctypes.com.util' module. It contains a 'w_getopt' function used
to parse Windows style command lines.