我有一个Windows DLL(XA_Session.dll)文件,但我不知道如何在golang中使用它。
这是一个DLL查看器图片
我想使用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 undefined(类型* syscall.LazyProc没有字段或方法ConnectServer)
答案 0 :(得分:2)
我的Direct3D9 Go wrapper中遇到了类似的问题,请参阅this thread,我可以从纯Go中调用DirectX COM函数。
在您的代码中,您尝试拨打proc.ConnectServer(...)
,但调用syscall.LazyProc
的方式是使用Call
功能。查看documentation for DllGetClassObject,签名是
HRESULT __stdcall DllGetClassObject(
_In_ REFCLSID rclsid,
_In_ REFIID riid,
_Out_ LPVOID *ppv
);
这意味着您必须将这三个参数传递给proc.Call
uintptr
s(Call
期望所有参数都为uintptr
s。
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
,AddRef
和Release
函数,然后是其他类型特定的方法。
假设你的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,
)
}
答案 1 :(得分:0)
https://github.com/go-adsi/adsi库具有ADSI COM对象的实现。它使用go-ole和comutil库。 对于其他COM对象用例来说,这可能是一个很好的起点。