Documentation
¶
Overview ¶
Package mscom implements COM(The Microsoft Component Object Model) object creation and invocation.
A COM interface is a struct contains a virtual function table(VMT) pointer. A VMT is a struct of MethodPtr(s). Neither the interface nor the VMT should contain go pointer practically, because they usually are handed out to C code(or the COM library). Allocating them using Alloc/AllocMem in this package or HeapAlloc like APIs.
For creating a COM object, call Init() on the VTM and then create methods use the *MethodCreator returned. CAUTION: Do not use the order of method in microsoft website, which may be reordered there!!
For using a COM object, invoke Call on the MethodPtr(s) in VTM.
If customized reference counting is not required, InitIUnknownImpl can be used as a helper to create COM objects. See CreateIUnknownImpl and other examples.
See type IUnknown and IMalloc for details.
Index ¶
- Variables
- func Alloc[T any]() *T
- func AllocMem(size uintptr) unsafe.Pointer
- func Cleanup[T any](obj *T)
- func CreateIUnknownImpl(ppObject **IUnknown) error
- func Free[T any](p *T)
- func FreeMem(p unsafe.Pointer)
- type IMalloc
- func (m *IMalloc) Alloc(size uintptr) unsafe.Pointer
- func (m *IMalloc) DidAlloc(p unsafe.Pointer) int
- func (m *IMalloc) Free(p unsafe.Pointer)
- func (m *IMalloc) GetSize(p unsafe.Pointer) uintptr
- func (m *IMalloc) HeapMinimize()
- func (m *IMalloc) IUnknown() *IUnknown
- func (m *IMalloc) Realloc(p unsafe.Pointer, size uintptr) unsafe.Pointer
- type IMallocVMT
- type IUnknown
- type IUnknownVMT
- type MethodCreator
- type MethodPtr
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var IID_IUnknown = gg.Must(sys.UuidFromStringW("00000000-0000-0000-C000-000000000046"))
Functions ¶
func Alloc ¶
func Alloc[T any]() *T
Alloc allocates a chunk of memory large enough to hold a T. Alloc using the OLE memory allocator(CoTaskMem[Alloc/Free]).
https://learn.microsoft.com/en-us/windows/win32/com/the-ole-memory-allocator "Whenever ownership of an allocated chunk of memory is passed through a COM interface or between a client and the COM library, you must use this COM allocator to allocate the memory. Allocation internal to an object can use any allocation scheme desired, but the COM memory allocator is a handy, efficient, and thread-safe allocator."
func Cleanup ¶
func Cleanup[T any](obj *T)
Cleanup is expected to be called when an object is released.
func CreateIUnknownImpl ¶
CreateIUnknownImpl creates an object which implements IUnknown interface. This function may also be considered as an example of creating COM objects with InitIUnknownImpl.
Types ¶
type IMalloc ¶
type IMalloc struct {
// contains filtered or unexported fields
}
Example ¶
package main import ( "fmt" "unsafe" "github.com/mkch/gw/mscom" "github.com/mkch/gw/mscom/sys" ) func main() { var malloc *mscom.IMalloc if r := sys.CoGetMalloc((*unsafe.Pointer)(unsafe.Pointer(&malloc))); r != sys.S_OK { panic(r) } defer malloc.IUnknown().Release() p := malloc.Alloc(5) if p == nil { panic("out of memory") } defer malloc.Free(p) n := malloc.GetSize(p) fmt.Println(n) }
Output: 5
func (*IMalloc) HeapMinimize ¶
func (m *IMalloc) HeapMinimize()
type IMallocVMT ¶
type IMallocVMT struct { IUnknownVMT // contains filtered or unexported fields }
type IUnknown ¶
type IUnknown struct {
// contains filtered or unexported fields
}
func (*IUnknown) QueryInterface ¶
type IUnknownVMT ¶
type IUnknownVMT struct {
// contains filtered or unexported fields
}
IUnknownVMT is the v-table of IUnknown interface. The doc(microsoft website) may reorder the method list. Refer to C source code to get the correct order.
type MethodCreator ¶
type MethodCreator methods
MethodCreator can be used to create method of COM object.
func Init ¶
func Init[T any](obj *T) *MethodCreator
Init initialize obj and returns the newly created method set.
func InitIUnknownImpl ¶
func InitIUnknownImpl[T any](obj *T, vt *IUnknownVMT, queryInterface func(sys.REFIID, *unsafe.Pointer) sys.HRESULT, release func()) (mtds *MethodCreator)
InitIUnknownImpl initializes an IUnknownVMT with a default implementation.
This function is a helper to implement arbitrary COM object. See CreateIUnknownImpl and other examples.
This implementation implements reference counting by atomic.Int32, and calling release when reference count reaches 0. It implements QueryInterface method for IID_IUnknown after checking param for E_POINTER and then calling queryInterface.
If queryInterface returns S_OK, the reference count is increased by 1 in this func. So don't increase the reference count in queryInterface itself. The returned MethodCreator is the result of calling Init(obj) and can be used to add more methods other than that of IUnknown.
Pitfall when declaring VMT: The method order of COM interface may be reorder in microsoft website!! So refer to the C source code to get the correct order.
Example ¶
package main import ( "fmt" "unsafe" "github.com/mkch/gg" "github.com/mkch/gw/mscom" "github.com/mkch/gw/mscom/sys" ) type INetworkListManagerEventsImplVMT struct { mscom.IUnknownVMT connectivityChanged mscom.MethodPtr } type INetworkListManagerEventsImpl struct { vt *INetworkListManagerEventsImplVMT } func (s *INetworkListManagerEventsImpl) IUnknown() *mscom.IUnknown { return (*mscom.IUnknown)(unsafe.Pointer(s)) } var IID_INetworkListManagerEvents = gg.Must(sys.UuidFromStringW("dcb00001-570f-4a9b-8d69-199fdba5723b")) func main() { var i *INetworkListManagerEventsImpl if err := CreateINetworkListManagerEventsImpl(&i); err != nil { panic(err) } defer i.IUnknown().Release() } func CreateINetworkListManagerEventsImpl(ppObject **INetworkListManagerEventsImpl) error { if ppObject == nil { return sys.HResultError(sys.E_POINTER) } // Alloc the interface and v-table in one block of memory. mem := mscom.Alloc[struct { INetworkListManagerEventsImpl INetworkListManagerEventsImplVMT }]() // Setup v-table. mem.INetworkListManagerEventsImpl.vt = &mem.INetworkListManagerEventsImplVMT // Call InitIUnknownImpl to initialize the IUnknownVMT part. mscom.InitIUnknownImpl(&mem.INetworkListManagerEventsImpl, &mem.IUnknownVMT, func(id sys.REFIID, p *unsafe.Pointer) sys.HRESULT { // This object can be converted to INetworkListManagerEvents interface. if *id == *IID_INetworkListManagerEvents { *p = unsafe.Pointer(&mem.INetworkListManagerEventsImpl) return sys.S_OK } return sys.E_NOINTERFACE }, func() { mscom.Free(mem) }). // Create the ConnectivityChanged method of INetworkListManagerEvents. Create(&mem.INetworkListManagerEventsImplVMT.connectivityChanged, func(connectivity uintptr) uintptr { fmt.Printf("connectivityChanged: %v\n", connectivity) return uintptr(sys.S_OK) }) *ppObject = &mem.INetworkListManagerEventsImpl return nil }
Output:
func (*MethodCreator) Create ¶
func (m *MethodCreator) Create(p *MethodPtr, f any) *MethodCreator
Create creates a method of an COM object. Argument p is the method pointer in v-table. Argument f is the function actually executed when the method is called. Function f is expected to be a function with zero or more uintptr arguments(method receiver must be omitted, we have closures in go) and one uintptr result. The return value is m itself to allow chained calls.