diff --git a/docs/source/client.rst b/docs/source/client.rst index b790279cd..51ffca1f9 100644 --- a/docs/source/client.rst +++ b/docs/source/client.rst @@ -13,39 +13,42 @@ Creating and accessing COM objects ``comtypes.client`` exposes three functions that allow to create or access COM objects. -``CreateObject(progid, clsctx=None, machine=None, interface=None, dynamic=False, pServerInfo=None)`` +.. py:function:: CreateObject(progid, clsctx=None, machine=None, interface=None, dynamic=False, pServerInfo=None) + Create a COM object and return an interface pointer to it. - ``progid`` specifies which object to create. It can be a string + *progid* specifies which object to create. It can be a string like ``"InternetExplorer.Application"`` or ``"{2F7860A2-1473-4D75-827D-6C4E27600CAC}"``, a ``comtypes.GUID`` instance, or any object with a ``_clsid_`` attribute that must be a ``comtypes.GUID`` instance or a GUID string. - ``clsctx`` specifies how to create the object, any combination of + *clsctx* specifies how to create the object, any combination of the ``comtypes.CLSCTX_...`` constants can be used. If nothing is passed, ``comtypes.CLSCTX_SERVER`` is used. - ``machine`` allows to specify that the object should be created on + *machine* allows to specify that the object should be created on a different machine, it must be a string specifying the computer name or IP address. DCOM must be enabled for this to work. - ``interface`` specifies the interface class that should be + *interface* specifies the interface class that should be returned, if not specified |comtypes| will determine a useful interface itself and return a pointer to that. - ``dynamic`` specifies that the generated interface should use + *dynamic* specifies that the generated interface should use dynamic dispatch. This is only available for automation interfaces and does not generate typelib wrapper. - ``pServerInfo`` that allows you to specify more information about - the remote machine than the ``machine`` parameter. It is a pointer - to a ``COSERVERINFO``. ``machine`` and ``pServerInfo`` may not be + *pServerInfo* that allows you to specify more information about + the remote machine than the *machine* parameter. It is a pointer + to a ``COSERVERINFO``. *machine* and *pServerInfo* may not be simultaneously supplied. DCOM must be enabled for this to work. -``CoGetObject(displayname, interface=None)`` + +.. py:function:: CoGetObject(displayname, interface=None) + Create a named COM object and returns an interface pointer to it. - For the interpretation of ``displayname`` consult the Microsoft + For the interpretation of *displayname* consult the Microsoft documentation for the Windows ``CoGetObject`` function. ``"winmgmts:"``, for example, is the displayname for `WMI monikers `_: @@ -57,8 +60,10 @@ access COM objects. ``interface`` and ``dynamic`` have the same meaning as in the ``CreateObject`` function. -``GetActiveObject(progid, interface=None)`` - Returns a pointer to an already running object. ``progid`` + +.. py:function:: GetActiveObject(progid, interface=None) + + Returns a pointer to an already running object. *progid* specifies the active object from the OLE registration database. The ``GetActiveObject`` function succeeds when the COM object is @@ -66,6 +71,7 @@ access COM objects. object table. Not all COM objects do this. The arguments are as described under ``CreateObject``. + All the three functions mentioned above will create the typelib wrapper automatically if the object provides type information. If the type library is not exposed by the object itself, the wrapper can be @@ -346,26 +352,29 @@ based on so-called *connection points*. handlers you should read the :doc:`server` document. -``GetEvents(source, sink, interface=None)`` +.. py:function:: GetEvents(source, sink, interface=None) + This functions connects an event sink to the COM object - ``source``. + *source*. - Events will call methods on the ``sink`` object; the methods must + Events will call methods on the *sink* object; the methods must be named ``interfacename_methodname`` or ``methodname``. The methods will be called with a ``this`` parameter, plus any parameters that the event has. - ``interface`` is the outgoing interface of the ``source`` object; + *interface* is the outgoing interface of the *source* object; it must be supplied when |comtypes| cannot determine the - outgoing interface of ``source``. + outgoing interface of *source*. ``GetEvents`` returns the advise connection; you should keep the connection alive as long as you want to receive events. To break the advise connection simply delete it. -``ShowEvents(source, interface=None)`` + +.. py:function:: ShowEvents(source, interface=None) + This function contructs an event sink and connects it to the - ``source`` object for debugging. The event sink will first print + *source* object for debugging. The event sink will first print out all event names that are found in the outgoing interface, and will later print out the events with their arguments as they occur. ``ShowEvents`` returns a connection object which must be kept @@ -375,11 +384,13 @@ based on so-called *connection points*. To actually receive events you may have to call the ``PumpEvents`` function so that COM works correctly. -``PumpEvents(timeout)`` + +.. py:function:: PumpEvents(timeout) + This functions runs for a certain time in a way that is required for COM to work correctly. In a single-theaded apartment it runs a windows message loop, in a multithreaded apparment it simply - waits. The ``timeout`` argument may be a floating point number to + waits. The *timeout* argument may be a floating point number to indicate a time of less than a second. Pressing Control-C raises a KeyboardError exception and terminates @@ -503,7 +514,8 @@ fortunately |comtypes| includes a code generator that does create modules containing the Python interface class (and more) automatically from COM typelibraries. -``GetModule(tlib)`` +.. py:function:: GetModule(tlib) + This function generates Python wrappers for a COM typelibrary. When a COM object exposes its own typeinfo, this function is called automatically when the object is created. @@ -588,7 +600,8 @@ from COM typelibraries. + from comtypes.gen.friendlymodule import __wrapper_module__ as mod c_int_alias = mod.TheName -``gen_dir`` +.. py:attribute:: gen_dir + This variable determines the directory where the typelib wrappers are written to. If it is ``None``, modules are only generated in memory. diff --git a/docs/source/com_interfaces.rst b/docs/source/com_interfaces.rst index c8fbe4c26..af4907c9e 100644 --- a/docs/source/com_interfaces.rst +++ b/docs/source/com_interfaces.rst @@ -35,24 +35,97 @@ Defining COM interfaces A COM interface in |comtypes| is defined by creating a class. The class must derive from ``comtypes.IUnknown`` or a subclass of -``IUnknown``. The interface class must define the following class -attributes: +``IUnknown``. - ``_iid_`` + +The ``IUnknown`` as a Python class +++++++++++++++++++++++++++++++++++ + +.. py:class:: comtypes.IUnknown + + In this package, ``IUnknown`` is defined as a pure Python class, + with all its high-level wrapper methods. + + .. py:method:: QueryInterface(interface, iid=None) + + This high-level method wraps the low-level `IUnknown::QueryInterface `_ + foreign function calls. This enables a Pythonic way of usage, + without worrying about pointers or passing by reference. + + *interface* is a ``IUnknown`` Python class or one of + subclasses. If the COM object implements the interface, + then it returns a pointer instance to that interface after + incrementing the reference count on it. + + *iid* is the optional interface identifier (IID). In most + cases, the *interface* class attribute is used to identify + the interface. However, passing a ``comtypes.GUID`` instance + can be useful in certain low-level processing scenarios. + + The return value is not a ``HRESULT`` value but a pointer to + the interface. If the COM object does **not** implement the + interface, a ``ctypes.COMError`` is raised with an ``hresult`` + of ``-2147467262`` (``E_NOINTERFACE``, ``'0x80004002'`` in + signed-32bit hex) + + .. py:method:: Add() + + This wraps the `IUnknown::AddRef `_. + Increments the reference count for an interface pointer to a + COM object and returns the new reference count. + + .. py:method:: Release() + + This wraps the `IUnknown::Release `_. + Decrements the reference count for an interface on a COM + object and returns the new reference count. + + In other COM technologies, it is necessary to explicitly + release COM pointers that have been created or copied by + calling ``Release``. However, in |comtypes|, explicit release + is not required because ``Release`` is automatically invoked + via ``atexit`` hooks or metaclasses when the Python + interpreter exits or when the Python instance is about to be + destroyed. + + In fact, explicitly releasing the pointer can cause issues; + if ``Release`` is called at the aforementioned timing, it may + raise an ``OSError``. + + .. sourcecode:: pycon + + >>> from comtypes.client import CreateObject, GetModule + >>> GetModule('UIAutomationCore.dll') # doctest: +ELLIPSIS + + >>> from comtypes.gen.UIAutomationClient import CUIAutomation + >>> iuia = CreateObject(CUIAutomation) + >>> iuia # doctest: +ELLIPSIS + + >>> iuia.Release() + 0 + >>> del iuia # doctest: +ELLIPSIS + Exception ignored in: + Traceback (most recent call last): + ... + OSError: exception: access violation writing ... + + The interface class must define the following class attributes: + + .. py:attribute:: _iid_ a ``comtypes.GUID`` instance containing the *interface identifier* of the interface - ``_idlflags_`` + .. py:attribute:: _idlflags_ (optional) a sequence containing IDL flags for the interface - ``_case_insensitive_`` + .. py:attribute:: _case_insensitive_ (optional) If set to ``True``, this interface supports case insensitive attribute access. - ``_methods_`` + .. py:attribute:: _methods_ a sequence describing the methods of this interface. COM methods of the superclass must not be listed, they are @@ -61,7 +134,7 @@ attributes: If one or more of the COM methods reference the interface class itself, it is possible to assign the ``_methods_`` attribute *after* the class statement like this: - + .. sourcecode:: python class ISomeInterface(IUnknown): @@ -69,14 +142,9 @@ attributes: ISomeInterface._methods_ = [...,] -.. note:: - - All the other attributes ``_iid_``, ``_idlflags_``, - ``_case_insensitive_`` must be defined when ``_methods_`` is set. - The ``_methods_`` list -++++++++++++++++++++++ +---------------------- Methods are described in a way that looks somewhat similar to an IDL definition of a COM interface. Methods must be listed in VTable @@ -86,7 +154,7 @@ There are two functions that create a method definition: ``STDMETHOD`` is the simple way, and ``COMMETHOD`` allows to specify more information. -``comtypes.STDMETHOD(restype, methodname, argtypes=())`` +.. py:function:: comtypes.STDMETHOD(restype, methodname, argtypes=()) Calling ``STDMETHOD`` allows to specify the type of the COM method return value. Usually *restype* is a ``HRESULT``, but other return @@ -95,7 +163,7 @@ information. method expects. -``comtypes.COMMETHOD(idlflags, restype, methodname, *argspec)`` +.. py:function:: comtypes.COMMETHOD(idlflags, restype, methodname, *argspec) *idlflags* is a list of IDL flags for the method. Possible values include ``dispid(aNumber)`` and ``helpstring(HelpText)``, as well as diff --git a/docs/source/conf.py b/docs/source/conf.py index c8538b624..b96cc1a29 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -110,7 +110,7 @@ # html_theme_options = {} # Add any paths that contain custom themes here, relative to this directory. -html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] +html_theme_path = [] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation".