guides:machine_code:com

This is an old revision of the document!


Using COM with MCode

When building integrations for AutoHotkey using MCode, it is often convenient to be able to work with COM objects. Either consuming COM objects in your MCode, or exporting COM objects from your MCode so they can be consumed by AHK.

The most basic COM object you can export from your MCode is an IUnknown object. To export an IUnknown object, you must implement the IUnknown interface's three methods: QueryInterface, AddRef, and Release.

IUnknown can't actually do anything worth demonstrating, so on top of those three methods we'll implement an additional three: SetFirstAddend, SetSecondAddend, and GetSum. Together, these will form our own custom interface, which we'll call IMyObj.

#Requires AutoHotkey v2.0
#include <MCL>
lib := MCL.FromC("
(
#include <mcl.h>
#include <stdlib.h>
#include <oaidl.h>
// --- Interface Identifiers ---------------------------------------------------
// IID_IUnknown {00000000-0000-0000-C000-000000000046}
GUID IID_IUnknown = { 0x00000000, 0x0000, 0x0000, { 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 } };
// IID_IMyObj (generated at random)
GUID IID_IMyObj = { 0x2D055F08, 0xC092, 0x44D4, { 0x82, 0xA9, 0xF7, 0x57, 0x75, 0x1D, 0x0D, 0x80 } };
// --- MyObj Structural Definition ---------------------------------------------
// Forward declare the MyObj type so it can be referenced in MyObjVtbl
typedef struct MyObj MyObj;
// Define the virtual method table for objects of type MyObj
typedef struct MyObjVtbl {
// Implements IUnknown
__stdcall HRESULT(*QueryInterface) (MyObj *this, REFIID riid, void **ppvObject);
__stdcall ULONG(*AddRef) (MyObj *this);
__stdcall ULONG(*Release) (MyObj *this);
 
הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

By implementing the IDispatch interface, your custom COM object can be wrapped by AHK. Once wrapped, users can interact with the object using native object syntax.

#Requires AutoHotkey v2.0
#include <MCL>
lib := MCL.FromC("
(
#include <mcl.h>
#include <stdlib.h>
#include <oaidl.h>
#define DISP_E_TYPEMISMATCH 0x80020005
MCL_IMPORT(int, msvcrt, _wcsicmp, (const short*, const short*));
MCL_IMPORT(HRESULT, OleAut32, VariantChangeType, (VARIANT*, const VARIANT*, USHORT, VARTYPE));
// --- Interface Identifiers ---------------------------------------------------
// IID_IUnknown {00000000-0000-0000-C000-000000000046}
GUID IID_IUnknown = { 0x00000000, 0x0000, 0x0000, { 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 } };
// IID_IDispatch {00020400-0000-0000-C000-000000000046}
GUID IID_IDispatch = { 0x00020400, 0x0000, 0x0000, { 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 } };
// --- MyObj Structural Definition ---------------------------------------------
// Forward declare the MyObj type so it can be referenced in MyObjVtbl
typedef struct MyObj MyObj;
// Define the virtual method table for objects of type MyObj
typedef struct MyObjVtbl {
// Implements IUnknown
 
הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX