This module add windows COM support to Winim. So that we can use Nim to interact with COM object like a script language. For example:
comScript: var dict = CreateObject("Scripting.Dictionary") dict.add("a", "the") dict.add("b", item:="quick") dict.add(item:="fox", key:="c") dict.item(key:="c") = "dog" for key in dict: echo key, " => ", dict.item(key)
This module introduce two new types to deal with COM objects: "com" and "variant". In summary, CreateObject() or GetObject() returned a "com" type value, and any input/ouput of COM method should be a "variant" type value.
Most Nim's data type and Winim's string type can convert to/from "variant" type value. The conversion is usually done automatically. However, specific conversion is aslo welcome.
proc toVariant[T](x: T): variant proc fromVariant[T](x: variant): T # Supported type: # char|string|cstring|mstring|wstring|BSTR # bool|enum|SomeInteger|SomeReal # com|variant|VARIANT|ptr IUnknown|ptr IDispatch|pointer # SYSTEMTIME|FILETIME # 1D~3D array|seq|COMBinary
COMBinary type can help to deal with binary data. For example:
var input = "binary\0string\0test\0" var v = toVariant(COMBinary input) var output = string fromVariant[COMBinary](v) assert input == output
Types
COMArray1D = seq[variant]
COMArray2D = seq[seq[variant]]
COMArray3D = seq[seq[seq[variant]]]
COMBinary = distinct string
comEventHandler = proc (self: com; name: string; params: varargs[variant]): variant
COMException = object of COMError
VariantConversionError = object of ValueError
Procs
proc `[]`(self: variant; name: string): variant {. ...raises: [Exception, VariantConversionError, COMError, COMException], tags: [RootEffect].}
proc call(self: com; name: string; vargs: varargs[variant, toVariant]): variant {. discardable, inline, ...raises: [Exception, COMError, VariantConversionError, COMException], tags: [RootEffect].}
proc call(self: com; name: string; vargs: varargs[variant, toVariant]; kwargs: openArray[(string, variant)] = []): variant {.discardable, inline, ...raises: [Exception, COMError, VariantConversionError, COMException], tags: [RootEffect].}
proc COM_FullRelease() {....raises: [Exception], tags: [RootEffect].}
-
Clean up all COM objects and variants.
Usually, we let garbage collector to release the objects. However, sometimes the garbage collector can't release all the object even we call GC_fullCollect(). Some object will create a endless process in this situation. (for example: Excel.Application). So we need this function.
Use -d:notrace to disable this function.
proc connect(self: com; handler: comEventHandler; riid: REFIID = nil): DWORD {. discardable, ...raises: [Exception, COMError], tags: [RootEffect].}
-
Connect a COM object to a comEventHandler. Return a cookie to disconnect (if needed). Handler is a user defined proc to receive the COM event. comEventHandler is defined as:
type comEventHandler = proc(self: com, name: string, params: varargs[variant]): variant
proc CreateObject(progId: string): com {....raises: [Exception, COMError], tags: [RootEffect].}
- Creates a reference to a COM object.
proc desc(self: com; name: string): string {....raises: [Exception, COMError], tags: [RootEffect].}
- Gets the description (include name and arguments) for the specified method.
proc disconnect(self: com; cookie: DWORD; riid: REFIID = nil): bool {. discardable, ...raises: [Exception, COMError], tags: [RootEffect].}
- Disconnect a COM object from a comEventHandler.
proc fromVariant[T](x: variant): T
proc get(self: com; name: string; vargs: varargs[variant, toVariant]): variant {. discardable, inline, ...raises: [Exception, COMError, VariantConversionError, COMException], tags: [RootEffect].}
proc get(self: com; name: string; vargs: varargs[variant, toVariant]; kwargs: openArray[(string, variant)]): variant {.discardable, inline, ...raises: [Exception, COMError, VariantConversionError, COMException], tags: [RootEffect].}
proc getCurrentCOMError(): ref COMError {.inline, ...raises: [], tags: [].}
proc GetObject(file: string; progId: string = ""): com {. ...raises: [Exception, COMError], tags: [RootEffect].}
- Retrieves a reference to a COM object from an existing process or filename.
proc newCom(file, progId: string): com {.inline, ...raises: [Exception, COMError], tags: [RootEffect].}
proc newVariant(x: VARIANT): variant {....raises: [VariantConversionError], tags: [].}
proc rawTypeDesc(x: variant): string {....raises: [], tags: [].}
proc set(self: com; name: string; vargs: varargs[variant, toVariant]): variant {. discardable, inline, ...raises: [Exception, COMError, VariantConversionError, COMException], tags: [RootEffect].}
proc set(self: com; name: string; vargs: varargs[variant, toVariant]; kwargs: openArray[(string, variant)]): variant {.discardable, inline, ...raises: [Exception, COMError, VariantConversionError, COMException], tags: [RootEffect].}
proc setRef(self: com; name: string; vargs: varargs[variant, toVariant]): variant {. discardable, inline, ...raises: [Exception, COMError, VariantConversionError, COMException], tags: [RootEffect].}
proc setRef(self: com; name: string; vargs: varargs[variant, toVariant]; kwargs: openArray[(string, variant)]): variant {.discardable, inline, ...raises: [Exception, COMError, VariantConversionError, COMException], tags: [RootEffect].}
proc toVariant(x: SYSTEMTIME): variant {....raises: [VariantConversionError], tags: [].}
Converters
converter variantConverterToBool(x: variant): bool {. ...raises: [VariantConversionError], tags: [].}
converter variantConverterToChar(x: variant): char {. ...raises: [VariantConversionError], tags: [].}
converter variantConverterToCom(x: variant): com {. ...raises: [VariantConversionError, Exception], tags: [RootEffect].}
converter variantConverterToCOMArray1D(x: variant): COMArray1D {. ...raises: [VariantConversionError], tags: [].}
converter variantConverterToCOMArray2D(x: variant): COMArray2D {. ...raises: [VariantConversionError], tags: [].}
converter variantConverterToCOMArray3D(x: variant): COMArray3D {. ...raises: [VariantConversionError], tags: [].}
converter variantConverterToCOMBinary(x: variant): COMBinary {. ...raises: [VariantConversionError], tags: [].}
converter variantConverterToCString(x: variant): cstring {. ...raises: [VariantConversionError], tags: [].}
converter variantConverterToFILETIME(x: variant): FILETIME {. ...raises: [VariantConversionError], tags: [].}
converter variantConverterToFloat32(x: variant): float32 {. ...raises: [VariantConversionError], tags: [].}
converter variantConverterToFloat64(x: variant): float64 {. ...raises: [VariantConversionError], tags: [].}
converter variantConverterToIDispatch(x: variant): ptr IDispatch {. ...raises: [VariantConversionError, Exception], tags: [RootEffect].}
converter variantConverterToInt(x: variant): int {. ...raises: [VariantConversionError], tags: [].}
converter variantConverterToInt8(x: variant): int8 {. ...raises: [VariantConversionError], tags: [].}
converter variantConverterToInt16(x: variant): int16 {. ...raises: [VariantConversionError], tags: [].}
converter variantConverterToInt32(x: variant): int32 {. ...raises: [VariantConversionError], tags: [].}
converter variantConverterToInt64(x: variant): int64 {. ...raises: [VariantConversionError], tags: [].}
converter variantConverterToIUnknown(x: variant): ptr IUnknown {. ...raises: [VariantConversionError, Exception], tags: [RootEffect].}
converter variantConverterToMString(x: variant): mstring {. ...raises: [VariantConversionError], tags: [].}
converter variantConverterToPointer(x: variant): pointer {. ...raises: [VariantConversionError], tags: [].}
converter variantConverterToString(x: variant): string {. ...raises: [VariantConversionError], tags: [].}
converter variantConverterToSYSTEMTIME(x: variant): SYSTEMTIME {. ...raises: [VariantConversionError], tags: [].}
converter variantConverterToUInt(x: variant): uint {. ...raises: [VariantConversionError], tags: [].}
converter variantConverterToUInt8(x: variant): uint8 {. ...raises: [VariantConversionError], tags: [].}
converter variantConverterToUInt16(x: variant): uint16 {. ...raises: [VariantConversionError], tags: [].}
converter variantConverterToUInt32(x: variant): uint32 {. ...raises: [VariantConversionError], tags: [].}
converter variantConverterToUInt64(x: variant): uint64 {. ...raises: [VariantConversionError], tags: [].}
converter variantConverterToVARIANT(x: variant): VARIANT {....raises: [], tags: [].}
converter variantConverterToWString(x: variant): wstring {. ...raises: [VariantConversionError], tags: [].}
Macros
macro comScript(x: untyped): untyped
-
Nim's dot operators .= only allow "a.b = c". With this macro, "a.b(c, d) = e" is allowed. Some assignment needs this macro to work. Moreover, this macro also translates named arguments to table constructor syntax which methods/properties related functions can accept (here we use := as assignment to avoid syntax conflict). For example:
comScript: dict.item("c") = "dog" dict.add(item:="fox", key:="c") excel.activeSheet.cells(1, 1) = "text" excel.activeSheet.range(cell1:="A1") = "text"