python呼叫golang並回調
最近折騰python互動,也真夠嗆的,一連玩了好幾天,被虐的不要不要的。天天各種百度,Google之間。
好吧,廢話少說,轉入我們的正題。其實,py呼叫go一般的函式,只是第一道坎,正主其實是py呼叫go,並且go還回調py!!!
網上其實這些問題很少,而且有且只有一篇關於go回撥py的。
就是如下一位大兄弟寫的:https://www.golangtc.com/t/59f858c04ce40d3bf47f5fbc
雖說他是說解決了,問題是下面的解決方案寫的真心有問題啊。。。其實,py呼叫go,他們是通過c來進行橋接(應該是這麼說吧),py<——>c<——>go,就是說,py一直認為自己是呼叫c,go也是如此,並不知其實他們是在互相操作。。。
那麼,好辦了,py呼叫go並且回撥,在py側,只要按照py呼叫c,並且回撥就可以了。go側則go呼叫c,並且回撥c,就可以了。
其實py側很簡單,隨便百度一下,應該是正確的。上面那大兄弟寫的方法就可以了。問題是go側,真心坑。。。
當py傳入自己的回撥,其實是被c包裝了一下,然後,go這邊接收的其實就是一個c的函式指標!在go裡面,c的函式指標,其實就是一個unsafe.Pointer,一個unsafe.Pointer,一個unsafe.Pointer,重要的事情說三次!!!但go獲得這東西,它只知道是一個地址啊,不知道是一個什麼東西。。。好吧,只能把它重新轉回c的函式指標,但這個過程必須要靠一個c函式做過渡!!!!
然而,這樣就出現一個坑了!!!那個c函式定義,居然不能跟匯出的go函式寫在同一個go檔案裡面!!!否則,會一直報重複定義的錯誤,呵呵。於是乎,只能這麼弄,分三個檔案:一個.h檔案,兩個.go檔案。
clib.h
#ifndef CLIB_H #define CLIB_H typedef void (*callback)(int); #endif
這是定義回撥結構的。
clibh.go
package main /* #include "clib.h" void TestCCB(int c, callback cb){ cb(c); } */ import "C"
這是定義go呼叫c函式的,而且這個必須要有,用來間接呼叫c回撥(py回撥)的。
main.go
package main /* #include "clib.h" extern void TestCCB(int c, callback cb); */ import "C" import ( "unsafe" ) //export TestCB func TestCB(a, b int, cb unsafe.Pointer){ c:=a+b C.TestCCB(C.int(c), (*[0]byte)(cb)) } func main() { }
然後這個,是匯出我們的正主:TestCB。其中的引數,cb就是針對c(py)回撥的,在函式體裡面,其實用TestCCB(中間c函式)來呼叫這個回撥,注意:上方extern void TestCCB(int c, callback cb);只能這麼弄了,不能直接在這個.go檔案寫它的定義。我就是為此折騰了好些天的,直接在裡面定義c中間函式,就直接報重複定義了。
然後,編譯命令要注意了:
go build -ldflags=-s -buildmode=c-shared -o foo.so clibh.go main.go
兩個.go檔案,必須要寫出來!就是上面那大兄弟說的連個go,當時我看著他說的這個名詞,愣了半天,不知他說啥。。。其實就是把該編譯的go都寫吧。。。不知為啥go編譯的時候,不會主動把同一個包的程式碼都編譯在一起。。。隨便,能用就行。。。
接下來,在py側,就很簡單了。。。
import ctypes lib = ctypes.CDLL('./foo.so') CGOFunc = ctypes.CFUNCTYPE(None, ctypes.c_int32) def GoCB(c): print("c =", c) cb = CGOFunc(GoCB) lib.TestCB(5, 6, cb)
這個網上都有說,其實就是py呼叫c介面,然後c又回撥py函式的做法。。。以上。
參考了幾個網址:
https://www.golangtc.com/t/59f858c04ce40d3bf47f5fbc
https://github.com/golang/go/wiki/cgo#function-pointer-callbacks
https://xiaowing.github.io/post/howto_call_a_go_func_via_funcpoint_from_cside/
https://studygolang.com/articles/2629