windows: Proc.Call() forces heap allocation, while syscall.SyscallN(Proc.Addr()) doesn't

62 views
Skip to first unread message

Lorenz Bauer

unread,
Aug 6, 2024, 9:29:31 AM8/6/24
to golang-nuts
Hi,

I'm looking at calling functions from a DLL on Windows. I found syscall.DLL to do the job:

    syscall.MustLoadDLL("foo.dll").MustFindProc("bar").Call(uintptr(unsafe.Pointer(&arg)))

Call() is annotated with //go:uintptrescapes, which causes arg to be heap allocated. Rewriting the snippet above seems to avoid the escape to heap:

    syscall.SyscallN(...MustFindProc("bar").Addr(), uintptr(unsafe.Pointer(&arg)))

Here is a fully worked snippet: https://go.dev/play/p/vJySh0z22uI The escape analysis shows that b doesn't escape:

go build -gcflags="-m=1" main.go
# command-line-arguments
./main.go:11:28: inlining call to syscall.MustLoadDLL
./main.go:12:26: inlining call to syscall.(*DLL).MustFindProc
./main.go:17:28: inlining call to syscall.(*Proc).Addr
./main.go:13:6: moved to heap: a
./main.go:14:11: ... argument escapes to heap
./main.go:17:18: ... argument escapes to heap

This is important for my use case because it would reduce allocations on a common operation.

The uintptrescapes annotation was added due to https://github.com/golang/go/issues/16035

A couple of questions:
- Is my analysis correct or am I missing something?
- Has anything changed in the last 8 years which means Proc.Call could be made to not escape its arguments?
- Does it make sense to document this on Proc.Call?

Thanks!
Lorenz

Reply all
Reply to author
Forward
0 new messages