为了账号安全,请及时绑定邮箱和手机立即绑定

如何在 Golang 中使用 COM(组件对象模型)

如何在 Golang 中使用 COM(组件对象模型)

Go
芜湖不芜 2022-01-17 18:04:01
我有一个 Windows DLL (XA_Session.dll) 文件,但我不知道如何在 golang 中使用它。这是一个 DLL 查看器图片我想使用ConnectServerCOM 方法。这是我的代码package mainimport (    "syscall"    "fmt")var (    mod = syscall.NewLazyDLL("XA_Session.dll")    proc = mod.NewProc("DllGetClassObject"))func main() {    var bConnect bool    bConnect = proc.ConnectServer("hts.ebestsec.co.kr", 20001)    if bConnect {        fmt.Println("Success")    } else {        fmt.Println("Fail")    }}编译错误:.\main.go:17: proc.ConnectServer undefined (type *syscall.LazyProc has no field or method ConnectServer)
查看完整描述

2 回答

?
胡说叔叔

TA贡献1804条经验 获得超8个赞

我在我的Direct3D9 Go 包装器中遇到了类似的问题,请参阅这个线程,在那里我能够从纯 Go 调用 DirectX COM 函数。


在您的代码中,您尝试调用proc.ConnectServer(...),但调用 a 的方法syscall.LazyProc是使用它的Call函数。查看 DllGetClassObject的文档,签名是


HRESULT __stdcall DllGetClassObject(

  _In_  REFCLSID rclsid,

  _In_  REFIID   riid,

  _Out_ LPVOID   *ppv

);

这意味着您必须将这三个参数传递给proc.Callas uintptrs(Call期望所有参数都是uintptrs)。


package main


import "syscall"


var (

    xaSession      = syscall.NewLazyDLL("XA_Session.dll")

    getClassObject = xaSession.NewProc("DllGetClassObject")

)


func main() {

    // TODO set these variables to the appropriate values

    var rclsid, riid, ppv uintptr

    ret, _, _ := getClassObject.Call(rclsid, riid, ppv)

    // ret is the HRESULT value returned by DllGetClassObject, check it for errors

}

请注意,您需要正确设置参数值,CLSID 和 IID 可能包含在库随附的 C 头文件中,我不知道这个 XA_Session 库。


在这种ppv情况下,将是指向您创建的 COM 对象的指针。要使用 Go 中的 COM 方法,您可以创建包装器类型,前提是您知道它定义的所有 COM 方法及其正确顺序。所有 COM 对象都支持和函数QueryInterface,然后支持其他类型特定的方法。AddRefRelease


假设您的 XA_Session 对象还支持这两个功能(同样,我不知道它真正支持什么,您必须查一下)


int ConnectServer(int id)

DisconnectServer()

那么你可以做些什么来将它包装在 Go 中:


package xasession


import (

    "syscall"

    "unsafe"

)


// NewXASession casts your ppv from above to a *XASession

func NewXASession(ppv uintptr) *XASession {

    return (*XASession)(unsafe.Pointer(ppv))

}


// XASession is the wrapper object on which to call the wrapper methods.

type XASession struct {

    vtbl *xaSessionVtbl

}


type xaSessionVtbl struct {

    // every COM object starts with these three

    QueryInterface uintptr

    AddRef         uintptr

    Release        uintptr

    // here are all additional methods of this COM object

    ConnectServer    uintptr

    DisconnectServer uintptr

}


func (obj *XASession) AddRef() uint32 {

    ret, _, _ := syscall.Syscall(

        obj.vtbl.AddRef,

        1,

        uintptr(unsafe.Pointer(obj)),

        0,

        0,

    )

    return uint32(ret)

}


func (obj *XASession) Release() uint32 {

    ret, _, _ := syscall.Syscall(

        obj.vtbl.Release,

        1,

        uintptr(unsafe.Pointer(obj)),

        0,

        0,

    )

    return uint32(ret)

}


func (obj *XASession) ConnectServer(id int) int {

    ret, _, _ := syscall.Syscall(

        obj.vtbl.ConnectServer, // function address

        2, // number of parameters to this function

        uintptr(unsafe.Pointer(obj)), // always pass the COM object address first

        uintptr(id), // then all function parameters follow

        0,

    )

    return int(ret)

}


func (obj *XASession) DisconnectServer() {

    syscall.Syscall(

        obj.vtbl.DisconnectServer,

        1,

        uintptr(unsafe.Pointer(obj)),

        0,

        0,

    )

}



查看完整回答
反对 回复 2022-01-17
?
慕勒3428872

TA贡献1848条经验 获得超6个赞

https://github.com/go-adsi/adsi库实现了 ADSI COM 对象。它使用 go-ole 和 comutil 库。这可能是其他 COM 对象用例的良好起点。


查看完整回答
反对 回复 2022-01-17
  • 2 回答
  • 0 关注
  • 1057 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信