Python and COM - PowerPoint PPT Presentation

1 / 112
About This Presentation
Title:

Python and COM

Description:

win32com.client.Dispatch kicks it all off. Demo import ni ... ie, any custom interface not based on IDispatch can be generated ... – PowerPoint PPT presentation

Number of Views:261
Avg rating:3.0/5.0
Slides: 113
Provided by: markhammon
Category:
Tags: com | custom | kicks | python

less

Transcript and Presenter's Notes

Title: Python and COM


1
Python and COM
  • Greg Stein
  • Mark Hammond

2
Tutorial Agenda
  • Introduction to COM
  • PythonCOM Framework
  • Using Python as a COM client
  • Using Python as a COM server
  • Advanced topics
  • Futures

3
Introduction to COM
4
COM/OLE and ActiveX
  • Component Object Model
  • Specification for implementing and defining
    objects
  • OLE is the old name, COM is the official name,
    ActiveX is the marketing name
  • All the same - the Microsoft Marketing Machine

5
What is a COM interface?
  • A technique for implementing objects
  • Uses a vtable to define methods
  • Does not have properties
  • Basically a C object with only public methods
  • But not C specific - just borrowed
    implementation technique
  • Allows implementation from other languages
  • All interfaces have a unique ID

6
IUnknown
  • Base class of all interfaces
  • Every COM object must implement
  • Defines object lifetimes
  • Reference counted using AddRef and Release
    methods
  • Defines techniques for querying the object for
    something useful
  • QueryInterface method
  • No other functionality - simply defines these 3
    methods

7
Custom interfaces
  • Any interface derived from IUnknown
  • Therefore must follow IUnknown rules for
    lifetimes
  • Derived?
  • Means object can be used as its base. Simple
    implementation using vtables
  • All interfaces are custom interfaces
  • Not a standard part of COM per-se, just follow
    its rules

8
Objects vs. Interfaces
  • Interfaces simply define functionality
  • Objects, once instantiated, implement the
    interface
  • Object class also has unique ID
  • Objects always provide multiple interfaces
  • At least IUnknown and some other functional
    interface

9
CLSIDs, GUIDs, UUIDs, IIDs
  • COM defines 128 bit identifier, and API for
    creating them
  • High degree of certainty that these are
    globally unique
  • All use the same type and implementation, acronym
    reflects different usage
  • IID Interface ID, GUID Globally Unique
    Identifier, CLSID Class ID, UUID
    Universally Unique Identifier, etc
  • API for converting to and from Strings

10
Registering Objects
  • Objects register themselves in the Windows
    Registry
  • Register with their Unique CLSID
  • Also register a name for the object
  • COM provides API for translating, but names are
    not guaranteed unique
  • Many objects self register

11
Creating Objects
  • Standard COM API for creation
  • CoCreateInstance, passing
  • CLSID identifying the object to create
  • IID identifying the initial interface requested

12
C Pseudo Code
  • // Create an object, but only get back
  • // IUnknown pointer, with new reference
  • IUnknown pUnk CoCreateInstance(MyObject,
    ...)
  • // Ask the object for a pointer to a useful
    implementation!
  • pUseful pUnk-gtQueryInterface( IID_IUseful, ...)
  • pUnk-gtRelease() // finished with this.
  • pUseful-gtDoSomethingUseful()
  • pUseful-gtRelease() // Object now dies

13
Custom Interface Example1 of 2
  • Native Interfaces using Word
  • You would be unlikely to use Word this way
  • Demonstrative purposes only!
  • gtgtgt import ni, win32com, pythoncomgtgtgt
    opythoncom.CoCreateInstance \
    ("Word.Application", None, pythoncom.CLSCTX_ALL
    , pythoncom.IID_IUnknown)gtgtgt oltPyIUnknown at
    0x834b04 with obj at 0x423474gt

14
Custom Interface Example2 of 2
  • gtgtgt o.QueryInterface( \
    pythoncom.IID_IPersist)ltPyIPersist at 0x85dd54
    with obj at 0x423464gt
  • Almost identical to the pseudo code above
  • In fact, Python is far better than C, as long
    as we support the required interfaces natively
  • No AddRef or Release required, or even exposed
  • Release() currently exposed, but not for long!

15
IDispatch - poor mans COM1 of 2
  • Also known as Automation
  • Derived from IUnknown
  • Defines vtable methods to determine dispatch
    methods and properties at runtime
  • Perfect for scripting languages which have no
    compile step, or which are not C!
  • Optionally uses Type Libraries so optimizations
    can be made at compile time

16
IDispatch - poor mans COM2 of 2
  • What many people know as COM
  • Microsoft marketing machine
  • In reality, a small, but somewhat useful part of
    COM
  • Many useful COM interfaces do not support
    IDispatch
  • Native MAPI, Active Scripting/Debugging, ActiveX
    Controls, Speech Recognition, etc
  • Very hard from C/C, very easy from VB

17
Core InterfacesIntroduction
  • COM tends to use interfaces for everything.
    Example
  • Instead of using a file pointer/handle, a
    Stream interface is used, which provides file
    like semantics
  • Anyone free to implement the stream interface
    using any technique they choose
  • Such interfaces not necessarily part of COM
    per-se, but we consider them core interfaces

18
Core InterfacesEnumerators
  • Enumerators provide access into a list of values
  • Provides Next, Skip, Reset and Clone methods
  • Different enumerator interfaces for different
    types
  • IEnumGUID - Enumerate list of GUIDs
  • IEnumFooBar - Enumerate list of FooBars!

19
Core InterfacesCollections
  • Alternative technique for accessing lists
  • Usually only used via IDispatch
  • Uses tricks only IDispatch has available, such
    as properties!
  • Therefore not a real interface
  • Used to provide array like semantics for VB, etc
  • Methods include Count() and Item(). Count often
    implied by len(), Item() often omitted.

20
Core InterfacesStreams and Storage
  • IStream provides file like semantics
  • IStorage provides file system like semantics
  • Programs can write to this specification without
    needing to know the destination of the data
  • COM provides implementations of these for
    structured storage files

21
Core InterfacesMonikers
  • Provide file name to object mapping semantics
  • Fundamental concept is to provide an indirection
    level to an underlying object, and a program
    neutral way of accessing the underlying object
  • File and URL Monikers do just that
  • Pointer monikers allow anyone to implement an
    abstract indirection to an object (e.g., into a
    message store, etc)

22
Core InterfacesConnectionPoints
  • Provides simple callback functionality
  • Client sets up connection point object
  • Object passed to Connection Point Container
    object
  • Container calls methods on the Connection Point
    when appropriate
  • Typically used as an event mechanism (e.g.,
    ActiveX Controls). This is how VB finds the list
    of events for an object.

23
Core InterfacesAnd the Rest
  • Plenty of others not listed here
  • Anything in core PythonCOM is considered core
  • By us, anyway - YMMV -)
  • Check out the sources, Help Files, or forthcoming
    documentation
  • Who was going to write that?
  • Extensions to PythonCOM - present and future

24
Error Handling
  • All methods use HRESULT return code
  • Multiple success codes, and many failure codes
  • ISupportErrorInfo interface for richer error
    information
  • IDispatch uses EXCEP_INFO structure
  • PythonCOM transparently maps these
  • More detail in Server section

25
PythonCOM Framework
26
PythonCOM Framework
  • Supports use of Python for both COM servers and
    COM clients
  • Easy for the Python programmer
  • Dispatch friendly with core support for most
    common vtable interfaces
  • Easily extended for new vtable interfaces

27
PythonCOM Extensions
  • Model allows for COM extension DLLs
  • Once loaded, looks like native support to the
    Python programmer
  • MAPI, ActiveX Scripting and Debugging all use
    this technique
  • Import them once, and PythonCOM will serve up
    their interfaces
  • Makes for stable core, with more frequent
    extension releases

28
Using Python as a COM client
29
Python COM ClientsThe Problem
  • Calling a COM object from Python
  • COM vtable C (not Python)
  • IDispatch removes vtable requirement
  • Imposes coding burden on client
  • IDispatch is still vtable based, so core problem
    remains

30
Python COM ClientsThe Answer
  • We need an intermediary between a Python object
    and COMs vtables
  • These are called interfaces (c.f. gateways
    for the server side - poor choice of terminology,
    but this is what we use!)

31
PythonCOM Interfaces1 of 3
  • Very similar to standard Python extension modules
  • Conceptually identical to wrapping any C object
    in Python
  • 11 mapping between the COM pointer and Python
    object
  • Pulls apart arguments using PyArg_ParseTuple
  • Makes call on underlying pointer
  • Handles errors, exceptions, and return values

32
PythonCOM Interfaces2 of 3
PythonCOM
Interface
Server
Interface
Client
Interface
33
PythonCOM Interfaces3 of 3
PythonCOM
Interface IDispatch
Client
Server
Wrapper
34
IDispatch vs. vtable
  • IDispatch implemented in PythonCOM.dll like any
    other interface
  • No Dynamic logic implemented in DLL
  • Only GetIDsOfNames and Invoke exposed
  • win32com.client Python code implements all
    IDispatch logic
  • Calls the above 2 methods dynamically to obtain
    method and property information

35
IDispatch Implementation
  • 2 modes of IDispatch usage
  • Dynamic, where no information about an object is
    known at runtime
  • All determination of methods and properties made
    at runtime
  • Static, where full information about an object is
    known before hand
  • Information comes from a Type Library
  • Not all objects have Type Libraries (including
    Python objects!)

36
Dynamic IDispatch Implementation1 of 5
  • Implemented by win32com.client.dynamic
  • Also makes use of win32com.client.build
  • Uses __getattr__ and __setattr__ methods in
    Python to implement its magic

37
Dynamic IDispatch Implementation2 of 5
  • Not perfect solution as
  • __getattr__ has no idea if the attribute being
    requested is a property reference or a method
    reference
  • No idea if the result of a method call is
    required (i.e., is it a sub or a function)
  • Python must guess at the variable types
  • Big problem tends to be byref params - by
    default these are not handled

38
Dynamic IDispatch Implementation3 of 5
  • win32com.client.Dispatch kicks it all off
  • Demo
  • gtgtgt import ni
  • gtgtgt from win32com.client import Dispatch
  • gtgtgt wDispatch(Word.Application)
  • gtgtgt w.Visible 1
  • Starts Winword, and makes it visible

39
Dynamic Dispatch Implementation4 of 5
  • Pros
  • No setup steps - just works
  • Provides quick scripting access to components
  • Cons
  • Relatively slow
  • You need to know the object model of the target.
    Not self documenting.
  • Actually, Python can make many objects self
    documenting, but this is beyond the scope of this

40
Dynamic Dispatch Implementation5 of 5
  • Smart Dispatch vs. Dumb Dispatch
  • To overcome some potential problems, Python
    attempts to use Type Info even for dynamic
    objects
  • Slows down considerably for certain objects
  • win32com.client.DumbDispatch provides alternative
    implementation which does not attempt to locate
    type information
  • For many servers, will provide excellent results
    and speed

41
Static Dispatch Implementation1 of 4
  • Generates .py file from Type Information
  • win32com.client.makepy does this
  • Python code then imports this module
  • Python knows everything about the object
  • No confusion between methods and properties
  • Byref args handled correctly
  • No dynamic lookups - much faster

42
Static Dispatch Implementation2 of 4
  • Demo
  • C\gt cd \Program Files\Microsoft Office\Office
  • C\gt \python\python \python\win32com\client\makepy
    .py msword8.olb gt \python\msword8.py
  • ...
  • Cgt start python
  • gtgtgt import msword8 grind, grind -)
  • gtgtgt w msword8.Application()
  • gtgtgt w.Visible 1

43
Static Dispatch Implementation3 of 4
  • Pros
  • ByRef args handled correctly
  • Result becomes a tuple in that case
  • All types handled correctly
  • Python knows the type required, so doesnt have to
    guess. More scope to coerce
  • Significantly faster
  • Python source file documents methods and
    properties available

44
Static Dispatch Implementation4 of 4
  • Cons
  • Need to hunt down type library
  • Need to enter cryptic command to generate code
  • No standard place to put generated code
  • Compiling code may take ages
  • Not real problem, as this is a once only step
  • Type library may not be available
  • Many Cons listed are not permanent - help would
    be appreciated!

45
Dispatch, VARIANTs and Python Types
  • VARIANT
  • COM concept for IDispatch interface
  • Just a C union, with a flag for the type, and an
    API for manipulating and converting
  • IDispatch always uses VARIANT objects
  • In reality, COM is not typeless - most servers
    assume a particular type in the variant
  • Most (only!) complex code in PythonCOM deals with
    VARIANT conversions

46
Dispatch, VARIANTs and Python Types
  • Python has 2 modes of conversion
  • Python type drives VARIANT type
  • Python knows no better
  • Creates VARIANT based on type of Python object
  • Known type drives VARIANT type
  • For static IDispatch, Python often known exactly
    type required
  • Attempt to coerce the Python object to VARIANT of
    this type

47
win32com.client Files1 of 2
  • makepy.py, dynamic.py
  • Static and dynamic IDispatch implementations
    respectively
  • build.py
  • Utility code used by both modules above
  • CLSIDToClass.py
  • Manages dictionary of Python classes, mapped by
    CLSID. Code generated by makepy.py automatically
    populates this.

48
win32com.client Files2 of 2
  • combrowse.py
  • Basic COM browser that requires Pythonwin.
    Simply double-click on it.
  • tlbrowse.py
  • Basic Type Library browser that requires
    Pythonwin
  • util.py
  • Utiility helpers
  • connect.py
  • Connection point client base class

49
Client Side Error Handling1 of 2
  • Client interfaces raise pythoncom.com_error
    exception
  • Exception consists of
  • HRESULT
  • 32 bit error code, defined by OLE
  • Error Message
  • Should be language independant
  • (cont.)

50
Client Side Error Handling2 of 2
  • COM Exception Tuple
  • Tuple of (wcode, AppName, AppMessage, HelpFile,
    HelpContext, scode), all of which are application
    defined
  • Exception object itself, or any part of it, may
    be None
  • Arg Error
  • Integer containing the argument number that
    caused the error
  • Often None if error does not relate to specific
    argument

51
SWIG and COM Client Interfaces1 of 3
  • Recent changes to SWIG allow it to generate
    client side native interfaces
  • ie, any custom interface not based on IDispatch
    can be generated
  • Uses existing SWIG functionality and M.O.
  • ie, maintain .i files, and SWIG generates .c
    files
  • Native MAPI support generated this way
  • Pretty serious API, and it works a treat!

52
SWIG and COM Client Interfaces2 of 3
  • Sample .i from MAPI
  • define TABLE_SORT_DESCEND TABLE_SORT_DESCENDHRES
    ULT MAPIInitialize( MAPIINIT_0 INPUT)HRESULT
    MAPILogonEx( ULONG INPUT, TCHAR
    inNullString, ... IMAPISession OUTPUT)

53
SWIG and COM Client Interfaces3 of 3
  • Notes
  • defines are carried into module
  • Many functions are completely trivial
  • SWIG handles input/output params
  • Scope for even better integration with COM
  • e.g., maybe the first cut at the .i could be
    generated from the Type Info.
  • More work and discussions with Dave Beazley
    needed!

54
Using Python as a COM server
55
Python COM ServersThe Problem
  • Exposing a Python object as a COM object
  • COM vtable C (not Python)
  • IDispatch removes vtable requirement
  • Imposes coding burden on client
  • Some interfaces are defined as a vtable
  • Answer we need an intermediary between COMs
    vtables and a Python object
  • These are called gateways

56
Gateways1 of 2
  • Gateways act as the intermediary
  • Hold reference to the Python object
  • Map C method calls into Python calls
  • Map parameters and return values
  • A gateway is a C object implementing a
    particular COM interface
  • Gateways are registered with the framework and
    instantiated as needed to support particular
    interfaces as they are requested

57
Gateways2 of 2
  • The default gateway supports IDispatch
  • All Python COM servers automatically support
    IDispatch
  • Default also supports ISupportErrorInfo, a
    standard interface for returning extended error
    information

58
Gateways3 of 3
PythonCOM
Gateway
Wrapper
Server
Gateway
Client
Gateway
59
Calling Python Methods
  • The Python COM framework defines an
    IDispatch-oriented protocol for how the gateways
    call into Python
  • _QueryInterface_ determine support for a
    particular COM interface
  • _GetIDsOfNames_ look up a dispatch identifier
    (DISPID) for a given name
  • _Invoke_ invoke a method with specified
    parameters

60
Policies1 of 2
  • Features of the gateway protocol
  • Non-intuitive for a Python programmer
  • Usually requires support structures for the
    DISPID handling
  • Subtleties with some of the parameters and return
    values
  • Result hard for Python programmers to write a
    COM server
  • Answer policy objects

61
Policies2 of 2
  • A policy specifies how to implement a Python
    COM server
  • The policy object maps the gateway protocol to
    the given implementation policy
  • The default policy is usually sufficient
  • Custom policies may be created and used
  • An advanced topic (discussed later)

62
Instantiation1 of 3
  • The framework calls the CreateInstance function
    in the win32com.server.policy module
  • Hard-wired call to CreateInstance, but behavior
    can easily be hooked through custom policies
  • When your COM object is registered, an additional
    registry key specifies the creator function
  • Typically mymodule.MyClass

63
Instantiation2 of 3
  • The registry key is read by the default policy
    and used to instantiate your object
  • COM does not provide additional parameters to
    your creator function (the __init__ method)
  • Make sure that any parameters have defaults
  • COM will provide this capability
  • Registry can specify a custom policy

64
Instantiation3 of 3
PythonCOM
policy.py CreateInstance(clsid, riid)
clsid, riid
clsid, riid
returned
returned
creates
Interface
pUnk
65
The Default Policy
  • Python server objects (instances) are annotated
    with special attributes
  • Typically specified as class attributes
  • Most are optional
  • _public_methods_
  • A list of strings specifying the methods that
    clients are allowed to call
  • This is the only required attribute

66
A Quick Example
class MyPythonServer _public_methods_
SomeMethod def SomeMethod(self, arg1,
arg2) do_some_work(arg1) return
whatever(arg2)
  • Note that the only difference for the Python
    programmer is the addition of the
    _public_methods_ attribute

67
Useful Attributes
  • _public_attrs_ what Python attributes should be
    exposed as COM Properties
  • _readonly_attrs_ which of the above should be
    considered read-only
  • _com_interfaces_ what COM interfaces beyond
    IDispatch are supported

68
Wrapping1 of 3
  • The process of associating a gateway instance and
    a policy instance with a particular Python
    instance is known as wrapping
  • Similarly, retrieving the Python instance is
    known as unwrapping
  • Objects returned by Python COM servers must be
    wrapped (the framework does not automatically
    wrap)

69
Wrapping2 of 3
  • This diagram shows the organization of the
  • objects involved in a Python COM server and
  • where the wrapping term came from

70
Wrapping3 of 3
  • Wrapping an object that will be returnedfrom
    win32com.server import util...def method(self,
    arg) ob whatever(arg) return util.wrap(ob)
  • Unwrapping (of an argument) is rare
  • You must know the object is a Python object (and
    what to do with it once unwrapped)
  • Usually used in relatively closed systems

71
Error Handling1 of 3
  • COM defines simple result codes with the HRESULT
    type and associated constants
  • Extended error information includes description,
    help file, context, etc
  • Returned via EXCEP_INFO structure in IDispatch or
    through ISupportErrorInfo
  • Framework maps Python exceptions to COM result
    codes and exceptions

72
Error Handling2 of 3
  • If the Python exception is an instance, then
    framework looks for special attributes to fill in
    COM extended exception information
  • Just raise an instance with the right attributes
  • See exception.Exception utility class
  • Otherwise, the framework does its best

73
Error Handling3 of 3
  • When called via IDispatch, it returns the
    exception via EXCEP_INFO
  • For non-Dispatch calls, the caller may follow up
    by using ISupportErrorInfo to retrieve the
    exception
  • ISupportErrorInfo is part of the base gateway
    class and is always present

74
Collections1 of 3
  • Collections are sequence-like objects that
    typically implement the Add, Remove, and Item
    methods and a Count property
  • Some Collections (such as those provided natively
    by VB) can be indexed using numbers (acts as a
    sequence) or using strings (acts as a mapping)
  • win32com.server.util.Collection is a simple
    numerically indexed Collection class

75
Collections2 of 3
  • The Item method is special
  • It should be the default method, meaning that
    VB can implicitly call it without using its name
  • The predefined DISPID_VALUE value refers to the
    default method
  • Item can be called with one parameter (the index)
    or with two parameters (an index and a new value
    to place at that index)
  • This duality is not handled well by the default
    policy nor server.util.Collection
  • Also beware the numeric vs. string indexing

76
Collections3 of 3
  • The Python COM framework defines returning a list
    or tuple to mean returning a SAFEARRAY of VARIANT
    values
  • This means your object must explicitly return an
    object that obeys the Collection protocol
  • A custom policy could be used to automatically
    wrap sequences with a Collection
  • Only recognizes list and tuple
  • avoids treating a string as a sequence
  • instances are not checked for sequence behavior

77
Enumerators1 of 3
  • Enumerators are used by clients to enumerate a
    collection (sequence)
  • VBScript automatically fetches an enumerator for
    script code such as for each item in
    collection
  • Standard COM protocol uses the predefined
    DISPID_NEWENUM value and calls IDispatchInvoke()
  • Default policy calls your _NewEnum method

78
Enumerators2 of 3
  • IEnumVARIANT is the interface used by Automation
    clients (such as VB)
  • Your returned enumerator must implement the
    IEnumVARIANT interface
  • Values returned from Next() are VARIANTs (see
    client section for discussion of COM enumerator
    interfaces)
  • Support for IEnumVARIANT part of core
  • Python datatypes are easily coerced into VARIANTs
    by the IEnumVARIANT gateway

79
Enumerators3 of 3
  • win32com.server.util.NewEnum(seq) will return an
    enumerator for a given sequence
  • Custom enumerators are easily written
  • Dynamic sequences
  • Special handling of enumerated values
  • Subclass from server.util.ListEnumerator,
    ListEnumeratorGateway, or write from scratch
  • New gateways needed for interfaces other than
    IEnumVARIANT

80
Server Utilities
  • Various functionality available in
    win32com.server.
  • ...connect connection points
  • ...exception exception handling
  • ...policy framework support
  • ...register server object registration
  • ...util miscellaneous utilities

81
win32com.server.connect
  • Supplies utilities and classes for the server
    side of connection points

82
win32com.server.exception
  • Exports a single class Exception
  • Constructor has keyword arguments for the status
    code, description, help file, etc.
  • The Exception class places these values into
    instance variables
  • The Python COM framework picks up the values for
    returning to the caller

83
win32com.server.policy
  • Framework knows about this file
  • Hard-coded reference, so it must exist
  • Provides CreateInstance for the framework
  • Provides hooks for custom policies and
    dispatchers
  • Defines various standard policies and dispatchers
  • Future the policies and dispatchers will move
    out to separate files for easier maintainability

84
win32com.server.register
  • Utilities for registering your COM servers
  • Two primary functions
  • RegisterServer()
  • UnregisterServer()
  • Typically, registration for servers in a file is
    performed when the file is run from the command
    line (e.g. python myservers.py)
  • RegisterServer() has many options see its doc
    string for more information

85
win32com.server.register Example
class MyClass _public_methods_ MyMethod
class definition if __name__
__main__ import sys from win32com.server
import register if len(sys.argv) gt 1 and
sys.argv1 --unregister register.Unregist
erServer(, The.ProgID) else register.Re
gisterServer(, MyModule.MyClass, progID
The.ProgID)
86
win32com.server.util
  • wrap()
  • unwrap()
  • NewEnum()
  • ListEnumerator class
  • ListEnumeratorGateway class
  • Collection class

87
win32com.makegw
  • Tool for interfaces and gateways
  • SWIG now my preference for interfaces - gateways
    somewhat harder
  • Generate once, and never again
  • compare with SWIG, which allows multiple
    generations - particularly useful as support is
    added after initial generation
  • Better than hand-coding
  • Active Scripting, Debugging and some others done
    this way

88
Advanced Topics
89
Advanced Dispatchers1 of 2
  • Debugging and tracing utility
  • Almost identical to policies simply delegate to
    actual policy
  • Only used during development, so zero runtime
    overhead in release
  • Implementation is not for speed, but for
    assistance in debugging
  • e.g., IIDs translated if possible to names, often
    using the registry or dictionary lookups, etc

90
Advanced Dispatchers2 of 2
  • Log information about your server
  • All method calls made
  • All IDispatch mapping
  • All QueryInterface requests
  • Dispatchers available that send to various
    debugging terminals
  • win32dbg debugger, win32trace utility, existing
    stdout, etc.
  • Easy to write your own if you have specific
    debugging requirements

91
Advanced Wrapping1 of 5
  • All Python server objects are wrapped with at
    least two objects the policy and the gateway
  • Caveat a custom policy may implement the actual
    server rather than using another object (see
    win32com.servers.dictionary)
  • Dispatchers can actually add a third layer into
    this group

92
Advanced Wrapping2 of 5
  • Since a gateway is referenced with a C
    interface pointer, Python cannot hold the
    reference
  • Wrap once more with a framework interface
    (well call it a PyInterface to distinguish from
    COM interfaces)
  • The PyInterface is removed by the framework
    (exposing the C pointer) when a PyInterface is
    returned by a server

93
Advanced Wrapping3 of 5
Interface
Python
C
Returned to COM client (the framework removes the
PyInterface)
94
Advanced Wrapping4 of 5
  • win32com.pythoncom.WrapObject() wraps a Python
    object with a gateway and a PyInterface
  • Pass it the policy object (which is wrapping the
    Python server object)
  • Optional parameter specifies the IID of a gateway
    to use for the wrapping (the gateway must be
    registered with the COM framework)

95
Advanced Wrapping5 of 5
  • Unwrapping is performed through a special COM
    interface IUnwrapPythonObject
  • pythoncom.UnwrapObject() queries for this
    interface on the COM object held within the
    PyInterface object that is passed
  • The base gateway class implements this COM
    interface (so all gateways have it)
  • The interfaces single method returns the
    gateways underlying Python object

96
Advanced Custom Policies1 of 7
  • Why use a custom policy?
  • Special error handling, creation, calling
    mechanisms, validation, etc
  • Write the policy class and enter the appropriate
    information into the registry so that the
    framework will use your policy
  • Be sure to use your custom policy when wrapping
    your objects

97
Advanced Custom Policies2 of 7
  • Other provided policies
  • BasicWrapPolicy handy base class
  • MappedWrapPolicy low level mapping-based
    handling of names and properties and methods
  • DesignatedWrapPolicy build onto the Mapped
    policy a way for objects to easily specify the
    properties and methods
  • DynamicPolicy determine methods and properties
    dynamically

98
Advanced Custom Policies3 of 7
  • Example custom instantiation
  • A single Python COM server was used to represent
    multiple COM objects
  • At instantiation time, it used the CLSID passed
    to the policy to look in the registry for more
    detailed information
  • A child/sub object was created, based on the
    registered information the COM server provided
    some generic behavior for all of the child objects

99
Advanced Custom Policies4 of 7
  • Example error handling
  • Returning KeyError or other Python exceptions
    to callers was undesirable
  • Wrap all Invokes with an exception handler that
    would map Python errors into a generic error
  • Let through pythoncom.com_error unchanged
  • If a magic registry value was present, then a
    full traceback was placed into the exception
    (rather than simply internal error)

100
Advanced Custom Policies5 of 7
  • Example data validation
  • If the server object had a _validation_map_
    attribute, then a custom validation method would
    be called for all Property puts
  • _validation_map_ would map a Property name to a
    type signature that the _validate_() method would
    test against
  • The Invoke method was hooked to call the
    _validate_() method

101
Advanced Custom Policies6 of 7
  • Example functions for Property get/put
  • The Item() method in Collections is really
    treated as a parameterized property
  • Using a custom policy, get_Item() can be
    differentiated from put_Item()
  • Allowed for get_Count() and the absence of
    put_Count() implied read-only

102
Advanced Custom Policies7 of 7
  • Example alter mechanism for specifying the
    available properties
  • Using the _validation_map_ from a previous
    example, the available properties are easily
    derived (simply the keys of the mapping)
  • Avoided duplication of property specification
    (one in _validation_map_ and one in
    _public_attrs_)

103
Advanced Threading1 of 2
  • Python is normally single threaded the least
    capable COM threading model
  • With care, it could be possible to mark an object
    as free threaded to fool how COM handles the
    object, but Python will continue to allow only
    one thread per process to run
  • This behavior is fine for many applications where
    Python is a COM client, but it breaks down for
    some server scenarios

104
Advanced Threading2 of 2
  • The problem can be reduced by applying patches
    with allow Python to be truly free-threaded
  • Slows down single thread case
  • Applies mainly to multiprocessor use
  • More work on threading is needed and is in
    progress on the Thread-SIG

105
Futures
106
Future Directions
  • Auto wrap and unwrap
  • COM
  • SWIG
  • makepy

107
Future Auto Wrapping
  • This could be done today, but wasnt
  • Leaving it to Python increased flexibility
  • Complexity involved with needing a way to specify
    two things during any wrapping process the
    policy and the gateway
  • Moving to COM will be an opportune time to
    change
  • Annotation through attributes will control
    wrapping process

108
Future COM1 of 3
  • What is COM ?
  • Upcoming revision of COM
  • Runtime services memory management,
    interceptors, object model changes, language
    independence, etc
  • see http//www.microsoft.com/cominfo

109
Future COM2 of 3
  • Python already has most of COMs facilities and
    matches its model strongly
  • Huge win for Python
  • Simplify COM programming even more
  • Will reduce the framework and associated
    overheads
  • Better language compatibilities
  • Major reduction in dependence on vtables
  • Better type handling

110
Future COM3 of 3
  • Any Python object can be a COM server, provided
    it is registered appropriately
  • Note that COM registration will be easier
  • Auto wrapping
  • import somedll will load the metadata from
    the DLL and automatically make its classes and
    constants available

111
Future SWIG
  • Depends largely on what Dave Beazley is willing
    to support!
  • Interface support needs more work
  • Framework is OK
  • Mainly adding all interfaces and types to SWIG
    library
  • Gateways still a long way off
  • Future here quite uncertain
  • Some sort of IDL parsing highly desirable

112
Future makepy
  • Functionally quite complete
  • Some cleanup desirable, but works well
  • Architectural issues outstanding
  • Where does generated code go?
  • Utilities for automatic generation
  • From program ID
  • Integration with COM browser
  • Integration with some GUI interface
Write a Comment
User Comments (0)
About PowerShow.com