从CGo中调用Go的COM对象方法

我在Go中创build了一个Direct3D9包装器 ,它使用CGo来与C中的COM对象进行交互。

我想摆脱在Windows下的C编译器的依赖,所以用户不必安装MinGW或Cygwin从Go使用DirectX。

问题是,d3d9.dll不公开C函数,但使用COM。 加载DLL(使用syscall.LoadLibrary("d3d9.dll") )后可以直接调用的唯一函数是Direct3DCreate9 。 这将返回一个COM对象,将所有function公开为方法。

如何在没有CGo的情况下从纯Go中调用COM对象方法?

我知道Go-OLE库声明它调用没有CGo的COM接口,但我不能从源代码中看到如何为Direct3D9做同样的事情。 一个简单的例子只有相关的部分将是非常有帮助的。

Solutions Collecting From Web of "从CGo中调用Go的COM对象方法"

(没有一个全面的答案,因为我没有时间去实际测试,但仍然…)

虽然MSDN大多数时候假设你使用一些内置了“粘合”的平台(例如Visual C ++™产品或类似的东西)来处理COM对象,事实上,可以使用纯的COM对象看看这里和这里的初学者。

研究这些资源,你可以知道,在“COM接口”上调用方法相当于正确地使用它的“VTBL”(虚拟函数T a BL e)块,该块总是位于相对于伪指令的公知位置由实例化COM对象的函数返回的“接口”“事物”。

go-ole包以简单的方式实现了在纯C中执行的操作,因此拥有“在一个COM对象上调用方法我们需要在其VTBL上操作”的知识,我们可以找到IDispatch支持的实现那个包。 所以我会从那里开始。


我也会直接进入go-ole问题跟踪器,要求实现一个示例代码,它将显示如何通过调用go-ole包中的函数以外的方式调用COM对象的处理程序上的方法。

我问过来自go-ole的人,就像@ kostix建议的那样。

这是解决方案:

d3d9一般不具有COM vtbl。 例如,它没有IDispatch接口。 所以你不能用d3d9的go-ole。 但是你可以通过编写所有接口来完成。

 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()) } 

(三)mattn