Skip to content

syscall(windows): callbacks from winapi not firing in Go #10973

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
cromega opened this issue May 28, 2015 · 4 comments
Closed

syscall(windows): callbacks from winapi not firing in Go #10973

cromega opened this issue May 28, 2015 · 4 comments

Comments

@cromega
Copy link

cromega commented May 28, 2015

I see some weirdness while trying to interface with the WaveOut API in Windows (8.1, 64-bit, go1.4.2).

A callback I defined in Go and passed to WaveOut is supposed to be triggered multiple times by the lowlevel library on certain events. After a certain point these callbacks don't seem to run in Go but running my app through apimonitor shows that the lowlevel library actually tries to fire them:

apimonitor_dump

I tried to reproduce the issue with some standalone code, this is what I have (Note: Of course the actual issue might not be related, I don't know exactly what the winmm API and the sound interface driver are doing. Plus my low-level coding skills are lame so the whole thing could be completely wrong):

Sample dll:

#include "stdafx.h"
#include "callbackwtfcpp.h"

BOOL APIENTRY DllMain(HMODULE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved)
{
    return TRUE;
}

typedef int (__stdcall *GoCallback)(int data);

GoCallback _cb;

DWORD WINAPI myThread(LPVOID lpParameter)
{
    _cb(2);
    return 0;
}

extern "C"
{
    void CALLBACK Set(GoCallback cb)
    {
        _cb = cb;
    }

    void CALLBACK Fire(void)
    {
        _cb(1);

        DWORD myThreadID;
        HANDLE myHandle = CreateThread(0, 0, myThread, 0, 0, &myThreadID);
        WaitForSingleObject(myHandle, 500);
        CloseHandle(myThread);
    }
}

Sample Go:

package main

import (
  "fmt"
  "syscall"
)

func main () {
  dll := syscall.MustLoadDLL(`callbackwtfcpp.dll`)
  set := dll.MustFindProc("Set")
  fire := dll.MustFindProc("Fire")

  callback := syscall.NewCallback(func(data int) (ret uintptr) {
    fmt.Printf("from callback: %v\n", data)
    return
  })

  set.Call(callback)
  fire.Call()

  dll.Release()
}

What I expect to see on the terminal is

from callback: 1
from callback: 2

but I only see:

from callback: 1
@mattn
Copy link
Member

mattn commented May 28, 2015

maybe dup #9240

but you can fix this problem with insrting 1 line import "C".

package main

import "C"
import (
    "fmt"
    "syscall"
)

func main() {
    dll := syscall.MustLoadDLL(`callbackwtfcpp.dll`)
    set := dll.MustFindProc("Set")
    fire := dll.MustFindProc("Fire")

    callback := syscall.NewCallback(func(data int) (ret uintptr) {
        fmt.Printf("from callback: %v\n", data)
        return
    })

    set.Call(callback)
    fire.Call()

    dll.Release()
}

@cromega
Copy link
Author

cromega commented May 29, 2015

Looks like I have to get a gcc toolchain up and running on windows for import "C" to work. I guess it would be easier to cross-compile the whole thing :)

I will post an update once I get down to it.

Thanks

@cromega
Copy link
Author

cromega commented May 30, 2015

@mattn: The cgo solution works indeed!

@alexbrainman
Copy link
Member

Dup of #6751.

Alex

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants