Convert callback function from C++ to Go

846 views
Skip to first unread message

Archos

unread,
Sep 10, 2012, 4:44:52 PM9/10/12
to golan...@googlegroups.com
How to "translate" in Go this C++ definition got in Windows? (winuser.h)

typedef LRESULT(CALLBACK *WNDPROC)(HWND,UINT,WPARAM,LPARAM);

It represents the WindowProc callback function

I've been seing in syscall_windows.go to find some callback like example but I did not find anyone. Although I found the
function NewCallback that I'm supposed it's just for this one but I need some example:

http://golang.org/src/pkg/syscall/syscall_windows.go#L111

Harley Laue

unread,
Sep 10, 2012, 5:57:32 PM9/10/12
to golan...@googlegroups.com
This seems to work in Wine (I don't have a windows machine in front of
me.) I also don't know if this is the best way to do this, but it
seems to work. Basically this sets up the syscall from user32 for
CallWindowProcA which then calls the Go function created with
syscall.NewCallback.

package main

import (
"fmt"
"syscall"
)

func main() {
cb := syscall.NewCallback(func(int, int, int, int) int {
fmt.Println("cb"); return 0})
wnd := syscall.NewLazyDLL("user32.dll")
wndProc := wnd.NewProc("CallWindowProcA")
wndProc.Call(cb, 0, 0, 0, 0)
}

brainman

unread,
Sep 10, 2012, 7:49:36 PM9/10/12
to golan...@googlegroups.com
On Tuesday, 11 September 2012 06:44:52 UTC+10, Archos wrote:

I've been seing in syscall_windows.go to find some callback like example but I did not find anyone. ...


# cd $GOROOT/src
# grep syscall.NewCallback * -r
pkg/runtime/syscall_windows_test.go:    cb := syscall.NewCallback(func(hwnd syscall.Handle, lparam uintptr) uintptr {
pkg/runtime/syscall_windows_test.go:    c := syscall.NewCallback(callback)
#

Also, http://code.google.com/p/gowingui/ has small app that uses syscall.NewCallback.

Alex

Andy Balholm

unread,
Sep 10, 2012, 11:12:53 PM9/10/12
to golan...@googlegroups.com
On Monday, September 10, 2012 2:57:39 PM UTC-7, Harley Laue wrote:
func main() {
        cb := syscall.NewCallback(func(int, int, int, int) int {
fmt.Println("cb"); return 0})
        wnd := syscall.NewLazyDLL("user32.dll")
        wndProc := wnd.NewProc("CallWindowProcA")
        wndProc.Call(cb, 0, 0, 0, 0)
}

Note that on 64-bit Windows the parameters and return value of the window proc are 64-bit. I don't think that Go ints have made that transition yet, so you may need to use some other type. (Either uintptr, or a type that is defined in a conditionally-compiled file.)

Archos

unread,
Sep 11, 2012, 6:21:37 AM9/11/12
to golan...@googlegroups.com
Ok, then i.e. I want to know when a window has changed its size, so:

// typedef LRESULT(CALLBACK *WNDPROC)(HWND,UINT,WPARAM,LPARAM);
func windowProc(hwnd syscall.Handle, msg uint32, wparam, lparam uintptr) (rc uintptr) {
     switch msg {
     case WM_SIZE:
         if wparam == SIZE_MAXIMIZED || wparam == SIZE_RESTORED {
             // HERE, I use a channel to notify to the Go application
         }
     default:
         return DefWindowProc(hwnd, msg, wparam, lparam)
     }
     return 1
}

wproc := syscall.NewCallback(windowProc)

And now, I'm supposing that wproc should be registered to the actual window, right? If it iso, how do it? Thanks in advance.

Andy Balholm

unread,
Sep 11, 2012, 12:00:51 PM9/11/12
to golan...@googlegroups.com
A WinAPI window belongs to a "window class". The window proc is set when the class is registered (with the RegisterClassEx function). It can also be changed later (for an individual window) by "subclassing" the window, but then you need to keep track of the old window proc and call it instead of DefWindowProc.
Reply all
Reply to author
Forward
0 new messages