-
Notifications
You must be signed in to change notification settings - Fork 6
Calling Windows API from Go
Calling Windows API from Go is pretty simple and straightforward as documented in official repository. So what I'm gonna list here are just some additional information about it.
It's recommended using golang.org/x/sys/windows
instead of standard syscall
if possible:
Yes, you should switch to x/sys. Some things crept into syscall under the covers, others went in because it's the job of that package to support the main repo and changes were required. But external packages should be using x/sys.
- Rob Pike from Google Groups
You can see there are lots of Windows APIs already defined in
golang.org/x/sys/windows
.
If you're gonna use only those Windows APIs listed there,
it's fine and encouraged to just use them. But if you find you need other APIs that are
not listed there, you should define it by your hands.
If a Windows API takes string as its parameter, there are two different versions of same API.
As you probably know,
ANSI and Unicode versions.
Strings in Go are basically unicode strings, so we'd use Unicode version of
Windows API that has W
prefix(e.g. MessageBoxW
) most of the time.
I recommend you to have Windows Data Types link in your bookmark bar. It's really helpful in situations like, when you get stuck wondering what LGRPID
type is.
For common data types that can be found on frequently used Windows APIs, I wrote a list of corresponding data type in Go. See Data Type Cheat Sheet for details.
Let's call MessageBoxW
from Go.
First you need to load system DLLs and find procedures. You can find several ways to do it, but here I'm gonna explain the easiest one:
libuser32 := windows.NewLazySystemDLL("user32.dll") // Load 'user32.dll' from Windows system directory
procMessageBoxW := libuser32.NewProc("MessageBoxW") // Find 'MessageBoxW' procedure inside the DLL
Notice that we use LazyDLL
and LazyProc
here so that our program only loads libraries it uses through runtime.
And that's all we need for our first API call.
We can now call the MessageBoxW
procedure from user32.dll
like this:
procMessageBoxW.Call(0, text, caption, 0)
But, here, as we pass strings to API, we have to convert strings to something that Windows API can understand.
golang.org/x/sys/windows.UTF16PtrFromString
is for this purpose.
You can use StringToUTF16Ptr
as well, but documentation says it is deprecated and use UTF16PtrFromString
instead.
So here's our code for text
and caption
:
text, err := windows.UTF16PtrFromString("Hello, World!")
if err != nil { ... }
caption, err := windows.UTF16PtrFromString("Go Windows Programming")
if err != nil { ... }
That's it. You can now see message box popping out.
See examples/syscall for details.