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
COMError = object of CatchableError hresult*: HRESULT
COMException = object of COMError
VariantConversionError = object of ValueError
com = ref object disp: ptr IDispatch
variant = ref object raw: VARIANT
COMArray = seq[variant]
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
Procs
proc len(x: COMBinary): int {...}{.borrow.}
proc high(s: COMBinary): int {...}{.borrow.}
proc low(s: COMBinary): int {...}{.borrow.}
proc cmp(x, y: COMBinary): int {...}{.borrow.}
proc `==`(x, y: COMBinary): bool {...}{.borrow.}
proc `<=`(x, y: COMBinary): bool {...}{.borrow.}
proc `<`(x, y: COMBinary): bool {...}{.borrow.}
proc substr(s: COMBinary; first, last: int): COMBinary {...}{.borrow.}
proc substr(s: COMBinary; first = 0): COMBinary {...}{.borrow.}
proc getCurrentCOMError(): ref COMError {...}{.inline, raises: [], tags: [].}
proc desc(e: ref COMError): string {...}{.raises: [], tags: [].}
proc del(x: com) {...}{.raises: [Exception], tags: [RootEffect].}
proc del(x: variant) {...}{.raises: [], tags: [].}
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 rawType(x: variant): VARTYPE {...}{.inline, raises: [], tags: [].}
proc rawTypeDesc(x: variant): string {...}{.raises: [], tags: [].}
proc newCom(x: ptr IDispatch): com {...}{.raises: [Exception], tags: [RootEffect].}
proc copy(x: com): com {...}{.inline, raises: [Exception], tags: [RootEffect].}
proc wrap(x: ptr IDispatch): com {...}{.inline, raises: [Exception], tags: [RootEffect].}
proc wrap(x: VARIANT): variant {...}{.inline, raises: [], tags: [].}
proc unwrap(x: com): ptr IDispatch {...}{.inline, raises: [], tags: [].}
proc unwrap(x: variant): VARIANT {...}{.inline, raises: [], tags: [].}
proc isNull(x: variant): bool {...}{.inline, raises: [], tags: [].}
proc newVariant(x: VARIANT): variant {...}{.raises: [VariantConversionError], tags: [].}
proc copy(x: variant): variant {...}{.raises: [VariantConversionError], tags: [].}
proc toVariant(x: string | cstring | mstring): variant
proc toVariant(x: wstring): variant {...}{.raises: [], tags: [].}
proc toVariant(x: BSTR): variant {...}{.raises: [], tags: [].}
proc toVariant(x: bool): variant {...}{.raises: [], tags: [].}
proc toVariant(x: SomeInteger | enum): variant
proc toVariant(x: SomeFloat): variant
proc toVariant(x: char): variant {...}{.raises: [], tags: [].}
proc toVariant(x: pointer): variant {...}{.raises: [], tags: [].}
proc toVariant(x: ptr IDispatch): variant {...}{.raises: [Exception], tags: [RootEffect].}
proc toVariant(x: com): variant {...}{.raises: [Exception], tags: [RootEffect].}
proc toVariant(x: ptr IUnknown): variant {...}{.raises: [Exception], tags: [RootEffect].}
proc toVariant(x: SYSTEMTIME): variant {...}{.raises: [VariantConversionError], tags: [].}
proc toVariant(x: FILETIME): variant {...}{.raises: [VariantConversionError], tags: [].}
proc toVariant(x: ptr SomeInteger | ptr SomeFloat | ptr char | ptr bool | ptr BSTR): variant
proc toVariant(x: VARIANT): variant {...}{.raises: [VariantConversionError], tags: [].}
proc toVariant(x: variant): variant {...}{.raises: [VariantConversionError], tags: [].}
proc toVariant(x: COMBinary): variant {...}{.raises: [VariantConversionError], tags: [].}
proc toVariant[T](x: openArray[T]; vt: VARENUM = VT_VARIANT): variant
proc fromVariant[T](x: variant): T
proc `$`(x: variant): string {...}{.inline, raises: [VariantConversionError], tags: [].}
proc desc(self: com; name: string): string {...}{.raises: [Exception, COMError], tags: [RootEffect].}
- Gets the description (include name and arguments) for the specified method.
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 call(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 set(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 setRef(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 get(self: com; name: string; vargs: varargs[variant, toVariant]): variant {...}{. discardable, inline, raises: [Exception, COMError, VariantConversionError, COMException], tags: [RootEffect].}
proc `[]`(self: variant; name: string): variant {...}{. raises: [Exception, VariantConversionError, COMError, COMException], tags: [RootEffect].}
proc CreateObject(progId: string): com {...}{.raises: [Exception, COMError], tags: [RootEffect].}
- Creates a reference to a COM object.
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(progId: string): com {...}{.inline, raises: [Exception, COMError], tags: [RootEffect].}
proc newCom(file, progId: string): com {...}{.inline, raises: [Exception, COMError], tags: [RootEffect].}
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 disconnect(self: com; cookie: DWORD; riid: REFIID = nil): bool {...}{.discardable, raises: [Exception, COMError], tags: [RootEffect].}
- Disconnect a COM object from a comEventHandler.
Converters
converter variantConverterToString(x: variant): string {...}{. raises: [VariantConversionError], tags: [].}
converter variantConverterToCString(x: variant): cstring {...}{. raises: [VariantConversionError], tags: [].}
converter variantConverterToMString(x: variant): mstring {...}{. raises: [VariantConversionError], tags: [].}
converter variantConverterToWString(x: variant): wstring {...}{. raises: [VariantConversionError], tags: [].}
converter variantConverterToChar(x: variant): char {...}{. raises: [VariantConversionError], tags: [].}
converter variantConverterToBool(x: variant): bool {...}{. raises: [VariantConversionError], tags: [].}
converter variantConverterToCom(x: variant): com {...}{. raises: [VariantConversionError, Exception], tags: [RootEffect].}
converter variantConverterToIDispatch(x: variant): ptr IDispatch {...}{. raises: [VariantConversionError, Exception], tags: [RootEffect].}
converter variantConverterToIUnknown(x: variant): ptr IUnknown {...}{. raises: [VariantConversionError, Exception], tags: [RootEffect].}
converter variantConverterToPointer(x: variant): pointer {...}{. raises: [VariantConversionError], tags: [].}
converter variantConverterToInt(x: variant): int {...}{.raises: [VariantConversionError], tags: [].}
converter variantConverterToUInt(x: variant): uint {...}{. raises: [VariantConversionError], tags: [].}
converter variantConverterToInt8(x: variant): int8 {...}{. raises: [VariantConversionError], tags: [].}
converter variantConverterToUInt8(x: variant): uint8 {...}{. raises: [VariantConversionError], tags: [].}
converter variantConverterToInt16(x: variant): int16 {...}{. raises: [VariantConversionError], tags: [].}
converter variantConverterToUInt16(x: variant): uint16 {...}{. raises: [VariantConversionError], tags: [].}
converter variantConverterToInt32(x: variant): int32 {...}{. raises: [VariantConversionError], tags: [].}
converter variantConverterToUInt32(x: variant): uint32 {...}{. raises: [VariantConversionError], tags: [].}
converter variantConverterToInt64(x: variant): int64 {...}{. raises: [VariantConversionError], tags: [].}
converter variantConverterToUInt64(x: variant): uint64 {...}{. raises: [VariantConversionError], tags: [].}
converter variantConverterToFloat32(x: variant): float32 {...}{. raises: [VariantConversionError], tags: [].}
converter variantConverterToFloat64(x: variant): float64 {...}{. raises: [VariantConversionError], tags: [].}
converter variantConverterToFILETIME(x: variant): FILETIME {...}{. raises: [VariantConversionError], tags: [].}
converter variantConverterToSYSTEMTIME(x: variant): SYSTEMTIME {...}{. raises: [VariantConversionError], tags: [].}
converter variantConverterToVARIANT(x: variant): VARIANT {...}{.raises: [], tags: [].}
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: [].}
Macros
macro `.`(self: com; name: untyped; vargs: varargs[untyped]): untyped
macro `.=`(self: com; name: untyped; vargs: varargs[untyped]): untyped
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"