猿问

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

我有一个 Windows DLL (XA_Session.dll) 文件,但我不知道如何在 golang 中使用它。

这是一个 DLL 查看器图片

我想使用ConnectServerCOM 方法。


这是我的代码


package main


import (

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


芜湖不芜
浏览 1059回答 2
2回答

胡说叔叔

我在我的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 mainimport "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 xasessionimport (    "syscall"    "unsafe")// NewXASession casts your ppv from above to a *XASessionfunc 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,    )}

慕勒3428872

https://github.com/go-adsi/adsi库实现了 ADSI COM 对象。它使用 go-ole 和 comutil 库。这可能是其他 COM 对象用例的良好起点。
随时随地看视频慕课网APP

相关分类

Go
我要回答