dongxian7194 2017-05-19 21:37 采纳率: 0%
浏览 594

如何使用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)
  • 写回答

1条回答 默认 最新

  • doufan9805 2017-08-25 08:59
    关注

    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.
    评论

报告相同问题?

悬赏问题

  • ¥15 微信会员卡接入微信支付商户号收款
  • ¥15 如何获取烟草零售终端数据
  • ¥15 数学建模招标中位数问题
  • ¥15 phython路径名过长报错 不知道什么问题
  • ¥15 深度学习中模型转换该怎么实现
  • ¥15 HLs设计手写数字识别程序编译通不过
  • ¥15 Stata外部命令安装问题求帮助!
  • ¥15 从键盘随机输入A-H中的一串字符串,用七段数码管方法进行绘制。提交代码及运行截图。
  • ¥15 TYPCE母转母,插入认方向
  • ¥15 如何用python向钉钉机器人发送可以放大的图片?