如何使用Cgo最少的DLL使用Go回调?

One way to setup a callback function to be passed in to a parameter to a DLL function is to use CGO...

package main

/*
#cgo LDFLAGS: -L${SRCDIR} -lsomelib

#include "somelib.h"

extern void CallbackString(char* s);
*/
import "C"

import (
    "unsafe"
    "fmt"
)

//export CallbackString
func CallbackString(s *C.char) {
    gostr := C.GoString(s)  // convert to golang string
    fmt.Println("Got string from dll (or dso): ", gostr)
}

func Example() {
    // setup a callback by calling a function in
    // the DLL requiring callback param
    C.SomeDLLFunc(x,y,
        (C.TCallbackString)(unsafe.Pointer(C.CallbackString)),
        other,
        params)
}


func main() {
    Example()
}

where the callback is defined as

typedef void (*TCallbackString)(char*);

But I am wondering if there is a way to avoid using CGO and just pass the go function in as a parameter without requiring needless C code bindings.. i.e.

C.SomeDLLFunc(x,y,
    CallbackString, // how to send the go function in as a callback?
    other,
    params)

Does it always require writing C bindings or whatever you call them, C links to the go code, C exports/externs, in order to send a callback as a param?

There is no way to just make a go function a callback without making it C-ish first?

C.SomeDLLFunc(x,y,
    WhatCastIsNeeded(CallbackString), // regular go function as a callback?
    other,
    params)

There is some way to avoid the cast and simplify callback code.

// cgo.h in dll  
typedef void (*Callback)(int kind,void* arg);
void SetCallback(Callback func);

// cgo.c in dll
Callback Gfunc;
void SetCallback(Callback func){
    Gfunc=func;
}

// cgocb.h in go project
void InitCallback();
extern void goCallbackFunction(int kind,void* arg);

// cgocb.c in go project
void InitCallback(){
    SetCallback(goCallbackFunction);
}

// cgocb.go in go project
// export goCallbackFunction
func goCallbackFunction(kind C.int,arg unsafe.Pointer){
    switch kind{
    case C.AKind:
        arg:=(*C.AKind)(arg)
        AkindCallback(arg)
    }
}
  1. The C.InitCallback function is similar to C.SomeDLLFunc.But it references goCallbackFunction directly without cast,since I move the code from .go to .c.
  2. This is a solution about callback to go from c dll. We need to register only one go function to the dll. We write one C.InitCallback. Note that if we use the C.SomeDLLFunc solution, we must write (gocallback,dllfunc) pairs.
  3. Keeping an export go function pointer in c dll is ok.