亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

從沒有 CGo 的 Go 調用 COM 對象方法

從沒有 CGo 的 Go 調用 COM 對象方法

Go
慕容3067478 2022-03-03 16:31:19
我在 Go 中創建了一個Direct3D9 包裝器,它使用 CGo 與 C 中的 COM 對象交互。我想擺脫對 Windows 下 C 編譯器的依賴,這樣用戶就不必安裝 MinGW 或 Cygwin 來使用 Go 中的 DirectX。問題是 d3d9.dll 不公開 C 函數,而是使用 COM。syscall.LoadLibrary("d3d9.dll")加載 DLL(帶有)后可以直接調用的唯一函數是Direct3DCreate9. 這將返回一個 COM 對象,該對象將所有功能公開為方法。如何在沒有 CGo 的情況下從純 Go 調用 DLL 中的 COM 對象方法?我知道Go-OLE庫,它聲明它在沒有 CGo 的情況下調用 COM 接口,但我無法從源代碼中看到我將如何為 Direct3D9 做同樣的事情。一個僅包含相關部分的簡單示例將有很大幫助。
查看完整描述

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

}


查看完整回答
反對 回復 2022-03-03
?
郎朗坤

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包中調用函數。


查看完整回答
反對 回復 2022-03-03
  • 2 回答
  • 0 關注
  • 290 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號