The ctypes COM framework

overview :: tutorial :: reference :: faq

( Work in progress: COM :: COM sample )

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.


SourceForge.net Logo
Page updated: Sat Mar 19 20:45:24 2005