Call COM object method from Go without CGo

I created a Direct3D9 shell in Go that uses CGo to interact with COM objects in C.

I would like to get rid of the dependency on the C compiler for Windows, so the user did not need to install MinGW or Cygwin to use DirectX with Go.

The problem is that d3d9.dll does not provide C functions, but uses COM. The only function that can be called immediately after loading the DLL (using syscall.LoadLibrary("d3d9.dll")) is Direct3DCreate9. This returns a COM object that provides all functions as methods.

How can I call COM object methods in a DLL from pure Go without CGo?

I know the Go-OLE library , which states that it calls COM interfaces without CGo, but I cannot see from sources how I continue to do the same for Direct3D9. A simple example with only relevant parts will be very useful.

+4
source share
2 answers

I asked go-ole guys, as @kostix suggested.

Here is the solution:

d3d9 does not have COM vtbl at all. for example, it does not have an IDispatch interface. Therefore, you cannot use go-ole for d3d9. But you can do this by writing the entire interface in go.

package main

import (
    "fmt"
    "log"
    "syscall"
    "unsafe"
)

const (
    D3D9_SDK_VERSION = 32
)

var (
    libd3d9             = syscall.NewLazyDLL("d3d9.dll")
    procDirect3DCreate9 = libd3d9.NewProc("Direct3DCreate9")
)

type IDirect3D struct {
    lpVtbl *IDirect3DVtbl
}

type IDirect3DVtbl struct {
    QueryInterface uintptr
    AddRef         uintptr
    Release        uintptr

    RegisterSoftwareDevice      uintptr
    GetAdapterCount             uintptr
    GetAdapterIdentifier        uintptr
    GetAdapterModeCount         uintptr
    EnumAdapterModes            uintptr
    GetAdapterDisplayMode       uintptr
    CheckDeviceType             uintptr
    CheckDeviceFormat           uintptr
    CheckDeviceMultiSampleType  uintptr
    CheckDepthStencilMatch      uintptr
    CheckDeviceFormatConversion uintptr
    GetDeviceCaps               uintptr
    GetAdapterMonitor           uintptr
    CreateDevice                uintptr
}

func (v *IDirect3D) AddRef() int32 {
    ret, _, _ := syscall.Syscall(
        v.lpVtbl.AddRef,
        1,
        uintptr(unsafe.Pointer(v)),
        0,
        0)
    return int32(ret)
}

func (v *IDirect3D) Release() int32 {
    ret, _, _ := syscall.Syscall(
        v.lpVtbl.Release,
        1,
        uintptr(unsafe.Pointer(v)),
        0,
        0)
    return int32(ret)
}

func (v *IDirect3D) GetAdapterCount() uint32 {
    ret, _, _ := syscall.Syscall(
        v.lpVtbl.GetAdapterCount,
        1,
        uintptr(unsafe.Pointer(v)),
        0,
        0)
    return uint32(ret)
}

func main() {
    v, r, err := procDirect3DCreate9.Call(uintptr(D3D9_SDK_VERSION))
    if r != 0 && err != nil {
        log.Fatal(err)
    }
    d3d := *((**IDirect3D)(unsafe.Pointer(&v)))

    d3d.AddRef()
    defer d3d.Release()

    fmt.Println(d3d.GetAdapterCount())
}

(c) mattn

0
source

(Not a complete answer, as I don’t have time to actually check this out, but still & hellip;)

MSDN , COM-, , "" ( Visual ++ & trade; product - ), COM-, C — .

, , "COM-" "VTBL" ( V irtual function T a BL e), , "", "", , COM-.

go-ole plain Go , C, " COM-, VTBL", IDispatch . .


go-ole , , COM, , go-ole.

+1

Source: https://habr.com/ru/post/1652569/


All Articles