syscall.NewCallback, floats and Windows

206 views
Skip to first unread message

Marco Ronchese

unread,
Mar 25, 2021, 2:38:10 PM3/25/21
to golang-nuts

Hello,

I am calling certain Windows API from Go code (without CGO), everything works flawlessly, but now I bumped into this issue.

I want to register a callback that accepts (also) a float as argument (https://docs.microsoft.com/en-us/windows/win32/api/audiopolicy/nf-audiopolicy-iaudiosessionevents-onsimplevolumechanged) and I get a runtime error:

panic: compileCallback: float arguments not supported


I tried to receive an uint32 and convert it with math.Float64frombits (well, basically just with some pointer arithmetic) but no luck.

This issue on Github (https://github.com/golang/go/issues/6510), which got fixed, is related, but there the syscall itself was returning floats, here is a callback to register with a syscall.

The questions are:
1) Can I work around this with some clever pointer conversion? From what I understand this is not the case since basically Go runtime is ignoring some CPU registers where that value is stored, am I right?
2) What is the philosophy behind the choice of not supporting this kind of stuff? Is something like: "Go runtime needs to support the basic syscall the language, its standard library and most users need, and for the rest C is the way"

A while back I though using CGO for these kind of stuff was the only way, few weeks ago I discover that this was not necessarily the case. I was thrilled I could write everything in Go, but maybe this is not true after all. Well, quite a journey. Of course I hope I am wrong

Thanks a lot,

Marco

Ian Lance Taylor

unread,
Mar 25, 2021, 3:46:06 PM3/25/21
to Marco Ronchese, golang-nuts
The problem is the calling convention. syscall.NewCallback has to
take the C values, which arrive using the C calling convention, and
pass them to Go using the Go calling convention. On amd64 the main
step here is callbackasm1 in runtime/sys_windows_amd64.s That
function takes the C argument registers and stores them in the right
place for the Go code. Unfortunately, on x86 floats are passed in
floating point registers, not the ordinary argument registers. So to
handle floating point arguments the code would need to get them from
the right register.

Not supporting this case is not a philosophical issue. It's that
nobody really knows how to implement it.

Ian

Marco Ronchese

unread,
Mar 25, 2021, 11:03:42 PM3/25/21
to golang-nuts
Thanks for the explanation.

I did some reading and I see there is some work going to switch to register-based calling convention (https://github.com/golang/go/issues/40724).
This could be a good occasion to try to fix this. In that issue is discussed which kind of SysCallbacks are needed, I will drop a comment and see what happens from there.

RP Junior

unread,
Mar 27, 2021, 9:55:03 PM3/27/21
to golang-nuts

May want to check out this setting on your issue:
 "cmd/internal/obj: reject splittable ABIInternal functions without morestack spill info (e.g., asm functions) because we can't generate a correct morestack path "
Unless of course you don't want to use asm functions

Marco Ronchese

unread,
Apr 5, 2021, 4:23:49 PM4/5/21
to golang-nuts
Just dropping here for reference the link to the Github issue: https://github.com/golang/go/issues/45300
Reply all
Reply to author
Forward
0 new messages