0
# Utilities and Support
1
2
Helper functions, type conversion utilities, SafeArray support, specialized interfaces for persistence and shell integration, error handling, and type library processing tools.
3
4
## Capabilities
5
6
### Memory and Type Utilities
7
8
Low-level utilities for memory manipulation and type conversion in COM operations.
9
10
```python { .api }
11
def byref_at(obj, offset):
12
"""
13
Create ctypes reference at memory offset.
14
15
Args:
16
obj: ctypes object
17
offset (int): Byte offset from object start
18
19
Returns:
20
ctypes reference pointing to offset location
21
"""
22
23
def cast_field(struct, fieldname, fieldtype):
24
"""
25
Cast structure field to different type.
26
27
Args:
28
struct: ctypes structure instance
29
fieldname (str): Name of field to cast
30
fieldtype (type): Target type for casting
31
32
Returns:
33
Field value cast to new type
34
"""
35
```
36
37
### SafeArray Support
38
39
Support for COM SafeArrays with automatic conversion to NumPy arrays when available.
40
41
```python { .api }
42
def _midlSAFEARRAY(itemtype):
43
"""
44
Create SAFEARRAY type for specified item type.
45
46
Args:
47
itemtype (type): Element type for array (e.g., c_int, c_double)
48
49
Returns:
50
SAFEARRAY type class for creating arrays of itemtype
51
"""
52
53
def safearray_as_ndarray(sa):
54
"""
55
Context manager for accessing SafeArray as NumPy array.
56
57
Args:
58
sa: SafeArray instance
59
60
Returns:
61
Context manager yielding NumPy array view
62
63
Usage:
64
with safearray_as_ndarray(safe_array) as np_array:
65
# Work with NumPy array
66
result = np_array.sum()
67
"""
68
```
69
70
### Error Information
71
72
Enhanced error handling with detailed COM error information.
73
74
```python { .api }
75
class IErrorInfo(IUnknown):
76
"""Interface for retrieving rich error information."""
77
78
def GetGUID(self):
79
"""
80
Get GUID of interface that defined the error.
81
82
Returns:
83
GUID: Interface identifier
84
"""
85
86
def GetSource(self):
87
"""
88
Get source of error (application name).
89
90
Returns:
91
str: Error source description
92
"""
93
94
def GetDescription(self):
95
"""
96
Get textual description of error.
97
98
Returns:
99
str: Error description
100
"""
101
102
def GetHelpFile(self):
103
"""
104
Get path to help file with error information.
105
106
Returns:
107
str: Help file path
108
"""
109
110
def GetHelpContext(self):
111
"""
112
Get help context ID for error.
113
114
Returns:
115
int: Help context identifier
116
"""
117
118
class ICreateErrorInfo(IUnknown):
119
"""Interface for creating error information objects."""
120
121
def SetGUID(self, guid):
122
"""Set interface GUID for error."""
123
124
def SetSource(self, source):
125
"""Set error source description."""
126
127
def SetDescription(self, description):
128
"""Set error description text."""
129
130
def SetHelpFile(self, helpfile):
131
"""Set help file path."""
132
133
def SetHelpContext(self, context):
134
"""Set help context ID."""
135
```
136
137
### HRESULT Management
138
139
Comprehensive HRESULT error code definitions and utility functions.
140
141
```python { .api }
142
# Success codes
143
S_OK: int # 0 - Success
144
S_FALSE: int # 1 - Success but false result
145
146
# General error codes
147
E_UNEXPECTED: int # Unexpected failure
148
E_NOTIMPL: int # Not implemented
149
E_NOINTERFACE: int # Interface not supported
150
E_POINTER: int # Invalid pointer
151
E_FAIL: int # Unspecified failure
152
E_INVALIDARG: int # Invalid argument
153
E_OUTOFMEMORY: int # Out of memory
154
155
# COM-specific errors
156
CLASS_E_NOAGGREGATION: int # Class doesn't support aggregation
157
CLASS_E_CLASSNOTAVAILABLE: int # Class not available
158
CO_E_CLASSSTRING: int # Invalid class string
159
160
# Connection point errors
161
CONNECT_E_CANNOTCONNECT: int # Cannot establish connection
162
CONNECT_E_ADVISELIMIT: int # Connection limit reached
163
CONNECT_E_NOCONNECTION: int # Connection doesn't exist
164
165
# Type library errors
166
TYPE_E_ELEMENTNOTFOUND: int # Element not found
167
TYPE_E_REGISTRYACCESS: int # Registry access error
168
TYPE_E_CANTLOADLIBRARY: int # Cannot load type library
169
170
# Dispatch errors
171
DISP_E_BADPARAMCOUNT: int # Wrong parameter count
172
DISP_E_TYPEMISMATCH: int # Type mismatch
173
DISP_E_UNKNOWNNAME: int # Unknown name
174
DISP_E_PARAMNOTOPTIONAL: int # Parameter not optional
175
176
# Utility functions
177
def MAKE_HRESULT(sev, fac, code):
178
"""
179
Construct HRESULT from severity, facility, and code.
180
181
Args:
182
sev (int): Severity (0=success, 1=error)
183
fac (int): Facility code
184
code (int): Error code
185
186
Returns:
187
int: Constructed HRESULT value
188
"""
189
190
def HRESULT_FROM_WIN32(x):
191
"""
192
Convert Win32 error code to HRESULT.
193
194
Args:
195
x (int): Win32 error code
196
197
Returns:
198
int: Equivalent HRESULT value
199
"""
200
```
201
202
### Persistence Interfaces
203
204
Interfaces for object persistence and property management.
205
206
```python { .api }
207
class IPersist(IUnknown):
208
"""Base interface for persistent objects."""
209
210
def GetClassID(self):
211
"""
212
Get class identifier for persistent object.
213
214
Returns:
215
GUID: Class identifier
216
"""
217
218
class IPropertyBag(IUnknown):
219
"""Interface for property bag persistence."""
220
221
def Read(self, propname, var, errorlog=None):
222
"""
223
Read property value from bag.
224
225
Args:
226
propname (str): Property name
227
var (VARIANT): Variable to receive value
228
errorlog (IErrorLog, optional): Error logging interface
229
"""
230
231
def Write(self, propname, var):
232
"""
233
Write property value to bag.
234
235
Args:
236
propname (str): Property name
237
var (VARIANT): Property value
238
"""
239
240
class IPersistPropertyBag(IPersist):
241
"""Interface for property bag persistence."""
242
243
def InitNew(self):
244
"""Initialize object to default state."""
245
246
def Load(self, propertybag, errorlog=None):
247
"""
248
Load object state from property bag.
249
250
Args:
251
propertybag (IPropertyBag): Property bag interface
252
errorlog (IErrorLog, optional): Error logging interface
253
"""
254
255
def Save(self, propertybag, cleardirty, saveallproperties):
256
"""
257
Save object state to property bag.
258
259
Args:
260
propertybag (IPropertyBag): Property bag interface
261
cleardirty (bool): Clear dirty flag after save
262
saveallproperties (bool): Save all properties or only dirty ones
263
"""
264
```
265
266
### Shell Integration
267
268
Interfaces for Windows shell integration and shell link manipulation.
269
270
```python { .api }
271
class IShellLinkW(IUnknown):
272
"""Unicode shell link interface for shortcut manipulation."""
273
274
def GetPath(self, flags=0):
275
"""
276
Get target path of shell link.
277
278
Args:
279
flags (int): Path retrieval flags
280
281
Returns:
282
str: Target path
283
"""
284
285
def SetPath(self, path):
286
"""
287
Set target path of shell link.
288
289
Args:
290
path (str): Target path
291
"""
292
293
def GetIDList(self):
294
"""
295
Get target as item ID list.
296
297
Returns:
298
ITEMIDLIST: Target item identifier list
299
"""
300
301
def SetIDList(self, pidl):
302
"""
303
Set target from item ID list.
304
305
Args:
306
pidl (ITEMIDLIST): Target item identifier list
307
"""
308
309
def GetDescription(self):
310
"""
311
Get shell link description.
312
313
Returns:
314
str: Description text
315
"""
316
317
def SetDescription(self, description):
318
"""
319
Set shell link description.
320
321
Args:
322
description (str): Description text
323
"""
324
325
def GetWorkingDirectory(self):
326
"""
327
Get working directory.
328
329
Returns:
330
str: Working directory path
331
"""
332
333
def SetWorkingDirectory(self, path):
334
"""
335
Set working directory.
336
337
Args:
338
path (str): Working directory path
339
"""
340
341
def GetArguments(self):
342
"""
343
Get command line arguments.
344
345
Returns:
346
str: Command line arguments
347
"""
348
349
def SetArguments(self, args):
350
"""
351
Set command line arguments.
352
353
Args:
354
args (str): Command line arguments
355
"""
356
357
class ShellLink(CoClass):
358
"""Shell link COM class for creating and manipulating shortcuts."""
359
_reg_clsid_ = "{00021401-0000-0000-C000-000000000046}"
360
_com_interfaces_ = [IShellLinkW]
361
```
362
363
### Stream Interfaces
364
365
Interfaces for stream-based I/O operations.
366
367
```python { .api }
368
class ISequentialStream(IUnknown):
369
"""Interface for sequential stream I/O operations."""
370
371
def RemoteRead(self, cb):
372
"""
373
Read data from stream (remote version).
374
375
Args:
376
cb (int): Maximum bytes to read
377
378
Returns:
379
bytes: Data read from stream
380
"""
381
382
def RemoteWrite(self, pv):
383
"""
384
Write data to stream (remote version).
385
386
Args:
387
pv (bytes): Data to write
388
389
Returns:
390
int: Number of bytes written
391
"""
392
```
393
394
### Type Library Tools
395
396
Tools for processing COM type libraries and generating Python bindings.
397
398
```python { .api }
399
def PTR(typ):
400
"""
401
Create pointer type descriptor for type library processing.
402
403
Args:
404
typ (type): Base type to create pointer for
405
406
Returns:
407
Pointer type descriptor
408
"""
409
410
def get_tlib_filename(tlib):
411
"""
412
Get filename for type library.
413
414
Args:
415
tlib: Type library reference (path, ProgID, or ITypeLib)
416
417
Returns:
418
str: Type library filename
419
"""
420
421
class Parser:
422
"""Type library parser for generating Python bindings."""
423
424
def __init__(self, tlib):
425
"""
426
Create parser for type library.
427
428
Args:
429
tlib: Type library to parse
430
"""
431
432
def generate_code(self):
433
"""
434
Generate Python code from type library.
435
436
Returns:
437
str: Generated Python code
438
"""
439
```
440
441
### Message Loop Support
442
443
Support for Windows message processing in COM applications.
444
445
```python { .api }
446
def run():
447
"""
448
Run Windows message loop.
449
Blocks until WM_QUIT message received.
450
"""
451
452
def insert_filter(filter_func):
453
"""
454
Insert message filter into message loop.
455
456
Args:
457
filter_func: Function to filter messages
458
Should return True to suppress message
459
"""
460
461
def remove_filter(filter_func):
462
"""
463
Remove message filter from message loop.
464
465
Args:
466
filter_func: Filter function to remove
467
"""
468
```
469
470
### Logging and Debugging
471
472
Utilities for debugging COM operations and logging COM activity.
473
474
```python { .api }
475
# Logger instance for comtypes package
476
logger: logging.Logger
477
"""Package logger for COM operations and debugging."""
478
479
class NullHandler(logging.Handler):
480
"""Logging handler that discards all messages."""
481
482
def emit(self, record):
483
"""Discard log record."""
484
pass
485
```
486
487
### Version Checking
488
489
Utilities for checking type library versions and compatibility.
490
491
```python { .api }
492
def _check_version(actual, required):
493
"""
494
Check if type library version meets requirements.
495
496
Args:
497
actual (tuple): Actual version as (major, minor)
498
required (tuple): Required version as (major, minor)
499
500
Returns:
501
bool: True if version is compatible
502
"""
503
```
504
505
## Usage Examples
506
507
### Working with SafeArrays
508
509
```python
510
import comtypes
511
from comtypes.safearray import _midlSAFEARRAY, safearray_as_ndarray
512
from ctypes import c_double
513
import numpy as np
514
515
# Create SafeArray type for doubles
516
DoubleArray = _midlSAFEARRAY(c_double)
517
518
# Create SafeArray with data
519
data = [1.0, 2.0, 3.0, 4.0, 5.0]
520
safe_array = DoubleArray.from_param(data)
521
522
# Access as NumPy array (if NumPy available)
523
with safearray_as_ndarray(safe_array) as np_array:
524
print(f"Sum: {np_array.sum()}")
525
print(f"Mean: {np_array.mean()}")
526
```
527
528
### Creating Shell Links
529
530
```python
531
import comtypes.client
532
from comtypes.shelllink import ShellLink, IShellLinkW
533
534
# Create shell link
535
link = comtypes.client.CreateObject(ShellLink, interface=IShellLinkW)
536
537
# Configure shortcut
538
link.SetPath(r"C:\Program Files\MyApp\myapp.exe")
539
link.SetDescription("My Application Shortcut")
540
link.SetWorkingDirectory(r"C:\Program Files\MyApp")
541
link.SetArguments("/startup")
542
543
# Save shortcut (would need IPersistFile interface)
544
# This is simplified - actual saving requires additional steps
545
```
546
547
### Error Handling with HRESULT
548
549
```python
550
import comtypes
551
from comtypes.hresult import *
552
553
try:
554
# Some COM operation that might fail
555
obj = comtypes.client.CreateObject("NonExistent.Application")
556
except comtypes.COMError as e:
557
if e.hresult == CLASS_E_CLASSNOTAVAILABLE:
558
print("COM class not registered")
559
elif e.hresult == E_NOINTERFACE:
560
print("Interface not supported")
561
else:
562
print(f"COM error: 0x{e.hresult:08X}")
563
```
564
565
### Memory Utilities
566
567
```python
568
import ctypes
569
from comtypes.util import byref_at, cast_field
570
571
# Create structure
572
class MyStruct(ctypes.Structure):
573
_fields_ = [
574
("field1", ctypes.c_int),
575
("field2", ctypes.c_double),
576
("field3", ctypes.c_char * 10)
577
]
578
579
s = MyStruct(42, 3.14, b"hello")
580
581
# Get reference to field at offset
582
field2_ref = byref_at(s, MyStruct.field2.offset)
583
584
# Cast field to different type
585
field_as_bytes = cast_field(s, "field3", ctypes.POINTER(ctypes.c_ubyte))
586
```
587
588
### Property Bag Persistence
589
590
```python
591
import comtypes
592
from comtypes.persist import IPropertyBag, IPersistPropertyBag
593
594
class MyPropertyBag:
595
"""Simple property bag implementation."""
596
597
def __init__(self):
598
self.properties = {}
599
600
def Read(self, name, var, errorlog=None):
601
if name in self.properties:
602
var.value = self.properties[name]
603
else:
604
raise comtypes.COMError(E_INVALIDARG)
605
606
def Write(self, name, var):
607
self.properties[name] = var.value
608
609
# Usage with persistent object
610
bag = MyPropertyBag()
611
# Save object properties to bag
612
# Load object properties from bag
613
```