gpt4 book ai didi

windows - 在没有 CGo 的情况下从 Go 调用 COM 对象方法

转载 作者:IT王子 更新时间:2023-10-29 00:45:03 24 4
gpt4 key购买 nike

我创建了一个 Direct3D9 wrapper在 Go 中,它使用 CGo 与 C 中的 COM 对象进行交互。

我想摆脱对 Windows 下 C 编译器的依赖,这样用户就不必安装 MinGW 或 Cygwin 就可以从 Go 中使用 DirectX。

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

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

我知道 Go-OLE库声明它在没有 CGo 的情况下调用 COM 接口(interface),但我无法从源代码中看到我将如何为 Direct3D9 做同样的事情。一个仅包含相关部分的简单示例会有很大帮助。

最佳答案

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

解决方法如下:

d3d9 doesn't have generally COM vtbl. for example, it doesn't have IDispatch interface. So you can't use go-ole for d3d9. But you can do it with writing all 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

关于windows - 在没有 CGo 的情况下从 Go 调用 COM 对象方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39162054/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com