Windows 如何在Golang中使用COM(组件对象模型)
我有一个Windows DLL(XA_Session.DLL)文件,但我不知道如何在golang中使用它 这是一个DLL查看器图片 我想使用Windows 如何在Golang中使用COM(组件对象模型),windows,dll,go,com,Windows,Dll,Go,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") ) fun
ConnectServer
COM方法
这是我的密码
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未定义(类型*syscall.LazyProc没有字段或方法ConnectServer)
我在我的中遇到了类似的问题,我可以从纯Go调用directxcom函数 在代码中,您尝试调用
proc.ConnectServer(…)
,但调用syscall.LazyProc
的方法是使用其call
函数。看这张照片,签名是
HRESULT __stdcall DllGetClassObject(
_In_ REFCLSID rclsid,
_In_ REFIID riid,
_Out_ LPVOID *ppv
);
这意味着您必须将这三个参数传递给proc.Call
作为uintpttr
s(Call
希望所有参数都是uintpttr
s)
请注意,您需要正确设置参数值,CLSID和IID可能包含在库的附带C头文件中,我不知道这个XA_会话库
在这种情况下,ppv
将是指向您创建的COM对象的指针。要使用Go中的COM方法,您可以创建包装器类型,前提是您知道它定义的所有COM方法及其正确顺序。所有COM对象都支持QueryInterface
、AddRef
和Release
功能,以及其他特定于类型的方法
假设您的XA_会话对象还支持这两个函数(同样,我不知道它真正支持什么,您必须查找)
然后,您可以执行以下操作将其包装到围棋中:
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,
)
}
库具有ADSI COM对象的实现。它使用go ole和comutil库。
这可能是其他COM对象用例的良好起点。您使用的
proc
不正确。它类似于函数DllGetClassObject的包装器,而不是DllGetClassObject返回的类对象。它没有这样的方法。我应该改变什么@我想用围棋使用com是相当困难的。试着更深入地研究com,看看这里。com不同于仅仅调用加载DLL的导出函数,因此我支持@V.Kravchenko,您可能应该使用专用包来处理com。至于调用导出函数,请查看Go源代码,特别是src/syscall
目录下名称与*\u windows.Go
匹配的文件:它们包含大量使用NewProc()
和syscall.syscall*()因此,我担心,实际上,用C++编译器生成的DLL与GO接口,您需要将DLL封装在另一个DC++中,C++编写并公开一个简单的C接口(通过<代码>外部)C“{…}”/COD>标准机制,封装这些C++方法,或者使用一个工具,如SWIG创建一个“桥”。“围棋代码。2) 在使用COM时,您不会直接加载提供COM对象的DLL,而是使用适当的Win32 API调用,通过COM对象的名称或GUID标识符间接为您实例化COM对象。然后间接地操作它。这就是go-ole
所做的。
int ConnectServer(int id)
DisconnectServer()
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,
)
}