std/com

COM on Windows, built on calling C, so a module that uses it is marked #![unsafe]. On other systems the module is empty.

#![unsafe]
import "std/com"

com_init()?
GUID shell_link = guid("{00021401-0000-0000-C000-000000000046}")
GUID link_w = guid("{000214F9-0000-0000-C000-000000000046}")
ComObject link = create_instance(shell_link, link_w)?
c_func(ptr[void], wstr) c_long set_description = ptr_cast(link.method(7))
check_hresult(set_description(link.pointer, "a link"), "SetDescription")?
link.close()

A COM object is a pointer to a table of C functions, its methods, each called with the object first: method(index) gives the one at index, QueryInterface, AddRef, and Release first, and the interface's own methods after them in the order it declares them, and a c_func of its signature calls it.

Function Result
com_init(), com_done() starts COM on this thread, in a single-threaded apartment, and ends it; OK(false) when it had started
check_hresult(result, doing) an HRESULT as a Result: an error of kind "com" with the system's message and the code, as 0x80004002, when it says failure
guid(text) the GUID written as "{...}"
same_guid(a, b) whether two GUIDs are one
create_instance(class_id, interface_id) a Result[ComObject]: a new object of a class, as one of its interfaces
com_wrap(pointer) a ComObject for a reference a function gave
com_method(pointer, index) the C function at index of an object's table
to_bstr(text), from_bstr(p), free_bstr(p) text as a BSTR and back
variant_int(n), variant_f64(x), variant_bool(b), variant_text(text) a VARIANT holding a value
variant_to_str(v) a Result[str]: the value of a VARIANT as text, the same in every language
clear_variant(v) frees what a VARIANT holds

A ComObject has the object's pointer, method(index), query(interface_id), which gives the object as another of its interfaces, and close(), which releases the reference; one that is not closed is released when the collector frees it.

A COM object written in Cuarzo, such as an event handler a library calls, has a ComClass: com_class(interfaces, methods) takes the GUIDs it answers QueryInterface for, besides IUnknown, and the C functions of its methods, made with c_callback, which take the object first. com_new(class, keep_alive(data)) makes an object with one reference that holds data, which its methods get back with kept(com_data(this)); the module counts its references, and frees it, and lets its data go, when the last one is released.