2 回答

TA貢獻1752條經驗 獲得超4個贊
我問了來自 go-ole 的人,就像 @kostix 建議的那樣。
這是解決方案:
d3d9 通常沒有 COM vtbl。例如,它沒有 IDispatch 接口。所以你不能將 go-ole 用于 d3d9。但是你可以通過在 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())
}

TA貢獻1921條經驗 獲得超9個贊
(不是一個全面的答案,因為我沒有時間實際測試這個,但仍然......)
雖然 MSDN 大部分時間都假設您使用具有內置“膠水”的平臺(例如 Visual C++? 產品或類似的東西)來處理 COM 對象,但實際上使用普通的 COM 對象是可能的C——在這里和這里尋找初學者。
研究這些資源,您可以了解到在“COM 接口”上調用方法相當于正確使用其“VTBL”(虛擬函數T a BL e)塊,該塊始終位于相對于偽裝的指針的知名位置實例化 COM 對象的函數返回的“接口”“事物”。
該go-ole
包在普通 Go 中實現了您在普通 C 中執行的操作,因此具備“調用 COM 對象上的方法,我們需要對其 VTBL 進行操作”的知識,我們可以在該包中找到IDispatch
支持的實現。所以我會從那里開始。
我還將直接進入go-ole
問題跟蹤器,要求實現一段示例代碼,該代碼將展示如何調用 COM 對象的處理程序上的方法,而不是從go-ole
包中調用函數。
- 2 回答
- 0 關注
- 290 瀏覽
添加回答
舉報