我有一个
Windows DLL(XA_Session.dll)文件,但我不知道如何在golang中使用它.
这是一个DLL Viewer图片
我想使用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 (type *syscall.LazyProc has no field or method ConnectServer)
最佳答案 我在
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
);
这意味着您必须将这三个参数作为uintptrs传递给proc.Call(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,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,
)
}