我在Go中创建了Direct3D9包装器,该包装器使用CGo与C中的COM对象进行接口。
我想摆脱Windows下对C编译器的依赖,因此用户不必安装MinGW或Cygwin即可使用Go中的DirectX。
问题在于d3d9.dll不会公开C函数,而是使用COM。加载DLL(带有syscall.LoadLibrary("d3d9.dll"))后,可以直接调用的唯一函数是Direct3DCreate9。这将返回一个COM对象,该对象将所有功能公开为方法。
syscall.LoadLibrary("d3d9.dll")
Direct3DCreate9
如何在没有CGo的纯Go中调用DLL中的COM对象方法?
我知道Go-OLE库,该库声明它在没有CGo的情况下调用COM接口,但是从源头上我看不到如何为Direct3D9做同样的事情。一个仅包含相关部分的简单示例将大有帮助。
我问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()) }
(c)马特恩