鍍金池/ 問答/C  C++  GO/ golang 調(diào)用 c的回調(diào)函數(shù)

golang 調(diào)用 c的回調(diào)函數(shù)

  1. golang 調(diào)用一個c的so庫, 函數(shù)RegisterCan

  2. c的回調(diào)函數(shù)結(jié)構(gòu)如下

typedef void (*CanCallBack)(int canChannel, char * canFrame, int canDataLen,unsigned long long canTime);

int RegisterCan(CanCallBack event);
  1. 要用go的實(shí)現(xiàn)CanCallBack回調(diào)函數(shù)的方法

網(wǎng)上找到相關(guān)cgo的說明,不是很懂,還望好心人給與提示

https://golang.org/cmd/cgo/#h...

回答
編輯回答
背叛者

不知道這個行不行
https://stackoverflow.com/que...

2017年5月4日 05:10
編輯回答
心上人

感謝各位的支持,已經(jīng)找到解決辦法

3個文件, can.go , load_so.c , load_so.h

can.go


/*
#include "load_so.h"
#cgo LDFLAGS: -ldl

*/
import "C"



//export CanProcess
func CanProcess(channel int, canFrame string, canDataLen int, timeOfCan uint64) {
    //TODO 具體回調(diào)業(yè)務(wù)
}

// 供外部調(diào)用
func Receive(){
    C.callback()
}

load_so.c

#include "load_so.h"
#include <dlfcn.h>

void CanProcess(int canChannel,char *  canFrame, int canDataLen,unsigned long long canTime);

int DoRegisterCan(CanCallBack event)
{
    void* handle;
    typedef int (*FPTR)(CanCallBack);

    handle = dlopen("./lib/filename.so", 1);
    if(!handle) {
         return -1;
       }
    FPTR fptr = (FPTR)dlsym(handle, "RegisterCan");

    int result = (*fptr)(event);
    return result;
}

int callback()
{
    return DoRegisterCan(CanProcess);
}

load_so.h

typedef void (*CanCallBack)(int canChannel, char * canFrame, int canDataLen,unsigned long long canTime);

int DoRegisterCan(CanCallBack event);

int callback();
2018年8月7日 04:56
編輯回答
維她命

說白了,題主需求的場景就是:

  • go語言側(cè)代碼調(diào)用第三方的C語言庫函數(shù),但是庫函數(shù)要求傳入一個函數(shù)指針作為回調(diào),然后題主想用cgo實(shí)現(xiàn)這個回調(diào)

golang官方關(guān)于cgo的wiki頁有詳細(xì)的關(guān)于題主詢問場景下的解決方法介紹。

主要是要做幾件事情:

  1. 用cgo實(shí)現(xiàn)這個回調(diào)函數(shù)的本體。比如實(shí)現(xiàn)一個類似下面這樣的cgo函數(shù),并將其導(dǎo)出

    func CanCallBack(canChannel  int, canFrame C.String, canDataLen int, 
    canTime uint64) {
        //...函數(shù)具體實(shí)現(xiàn)
    }

    以上偽代碼是隨手寫的,主要是參數(shù)類型不知道是否合適,特別是那個char 的參數(shù)需要根據(jù)實(shí)際情況來決定在cgo中定義成什么。*

  2. 在注釋部分用C語言語法實(shí)現(xiàn)一個gateway function(gateway function的介紹可參見上文給出的鏈接,gateway function的簽名必須和函數(shù)指針一致)。在這個gateway function中通過上述回調(diào)函數(shù)的導(dǎo)出簽名來調(diào)用上述回調(diào)函數(shù)

  3. 在你想調(diào)用第三方庫函數(shù)代碼的cgo代碼中調(diào)用這個第三方函數(shù),傳參時把上述gateway function的函數(shù)名傳入

總得來說就是以上三件事,但是具體寫代碼時還有一些細(xì)節(jié)需要注意的,我之前寫過一篇博客有提到這些注意點(diǎn),感興趣的話,題主可以參考一下:

C語言程序通過函數(shù)指針調(diào)用Go函數(shù)的方法

我寫的這篇博客討論的場景和題主期待的場景略有不同,望注意. 不過這里面存在的坑是共通的,比如說必須定義為main包之類的

2017年10月2日 05:41