84090

How to use COM (Component Object Model) in Golang

I have a Windows DLL (XA_Session.dll) file but I don't know how to use it in golang.

This is a DLL Viewer picture

<img src="https://i.stack.imgur.com/ppSY5.jpg" alt="">

I want to use the ConnectServer COM Method.

Here is my code

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

compile error:

.\main.go:17: proc.ConnectServer undefined (type *syscall.LazyProc has no field or method ConnectServer)

Answer1:

I had a similar problem in my Direct3D9 Go wrapper, see this thread, where I was able to call DirectX COM functions from pure Go.

In your code you try to call proc.ConnectServer(...) but the way to call a syscall.LazyProc is with its Call function. Looking at the documentation for DllGetClassObject, the signature is

HRESULT __stdcall DllGetClassObject( _In_ REFCLSID rclsid, _In_ REFIID riid, _Out_ LPVOID *ppv );

This means you have to pass these three parameters to proc.Call as uintptrs (Call expects all arguments to be 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 }

Note that you need to set the parameter values correctly, the CLSID and IID may be contained in the accompanying C header file for the library, I don't know this XA_Session library.

The ppv will in this case be a pointer to the COM object that you created. To use COM methods from Go, you can create wrapper types, given you know all the COM methods defined by it and their correct order. All COM objects support the QueryInterface, AddRef and Release functions and then additional, type specific methods.

Let's say your XA_Session object additionally supports these two functions (again, I don't know what it really supports, you have to look that up)

int ConnectServer(int id) DisconnectServer()

then what you can do to wrap that in Go is the following:

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, ) }

Recommend

  • I am having Directx 11 but WDDM 1.0 ? how to update it to WDDM 1.1? [duplicate]
  • How to detect whether I need to install VCRedist?
  • error LNK2001: unresolved external symbol _IID_IDirectDraw2
  • Difficulties implementing the Hysteresis step of Canny Algorithm in Halide without define_extern fun
  • Using Python objects in C++
  • CSS how to fix an element to scroll horizontally with the page but not vertically?
  • Where can I get Microsoft.DirectX.dll?
  • How to get current document uri in XSLT?
  • How to determine if there are bytes available to be read from boost:asio:serial_port
  • Unity3D & Android: Difference between “UnityMain” and “main” threads?
  • Retrieving value from sql ExecuteScalar()
  • Spray.io: When (not) to use non-blocking route handling?
  • output of program is not same as passed argument
  • Does CUDA 5 support STL or THRUST inside the device code?
  • Perl system calls when running as another user using sudo
  • Trying to switch camera back to front but getting exception
  • Statically linking a C++ library to a C# process using CLI or any other way
  • Adding custom controls to a full screen movie
  • Why winpcap requires both .lib and .dll to run?
  • SVN: Merging two branches together
  • Hibernate gives error error as “Access to DialectResolutionInfo cannot be null when 'hibernate.
  • KeystoneJS: Relationships in Admin UI not updating
  • Load html files in TinyMce
  • Acquiring multiple attributes from .xml file in c#
  • Free memory of cv::Mat loaded using FileStorage API
  • Hits per day in Google Big Query
  • Angular 2 constructor injection vs direct access
  • How to CLICK on IE download dialog box i.e.(Open, Save, Save As…)
  • Change div Background jquery
  • How does Linux kernel interrupt the application?
  • How can I remove ASP.NET Designer.cs files?
  • Checking variable from a different class in C#
  • Programmatically clearing map cache
  • Busy indicator not showing up in wpf window [duplicate]
  • Binding checkboxes to object values in AngularJs
  • Why do underscore prefixed variables exist?
  • java string with new operator and a literal
  • Net Present Value in Excel for Grouped Recurring CF
  • jQuery Masonry / Isotope and fluid images: Momentary overlap on window resize
  • How to load view controller without button in storyboard?