This is a creation in Article, where the information may have evolved or changed.
The introduction module, which needs to be shown in Go C
, allows the compiler to support the generation of dynamic-link libraries, and the use of C-language data types in code is critical. Calling Go code from Python code extraction One of the simplest examples
//libadd.gopackage mainimport "C"//export addfunc add(left, right int) int { return left + right}func main() {}
go build -buildmode=c-shared -o libadd.so libadd.go
from ctypes import cdlllib = cdll.LoadLibrary('./libadd.so')print("Loaded go generated SO library")result = lib.add(2, 3)print(result)
The CGO Export command go doc cgo
is documented in, section "C references to Go". Essentially, write //export FUNCNAME
before the function definition
There is a passage that requires an explicit comment to //export add
expose the Add function to the C call
This thought very simple can use, the interest is full to change the example, changed the simple processing string, but found that cannot run up.
//libadd.gopackage mainimport "C"//export addfunc add(left, right string) string { return left + right}func main() {}
from ctypes import CDLLlib = CDLL('./libadd.so')print("Loaded go generated SO library")result = lib.add("Hello", "World")print(result)
The Python code is really short and this are only passing an integer back and forth (more complex string and struct cases a Re much more challenging).
This means that it is not easy to change the string to a string
type. This time opened the building PYTHON MODULES with GO 1.5, when the most comprehensive information can be found, unfortunately the process is too complex, the whole idea is to write C code with go, similar Write the interpreter like, to abstract out the Pyobject and then follow the API standard to register, process, return. I just want to be 动态链接库
able to invoke it in a way that can be called.
I began to think about why the use of the type in the example int
, I changed to a simple receive string
return has string
failed. PY is used ctypes
to interact with so modules, there is a code translation process Py -> C -> Go
, What I can think of is that the processing of the string data type is not the same cause (as it turns out I guess). So think about it, what type of string in the Py is passed to go and what types are used to receive it? Read a lot of information, all the answers in the Python DOC official website about the ctypes
module can be found. Let's take a look at this picture:
001.png
Here you can see clearly the ctypes
string in Python3 bytes
and the string
corresponding two pointer types. also provides argtypes
and restype
to explicitly convert the parameters and return types of functions in a dynamic-link library. ( Reference StackOverflow)
At this time, follow the thought process to modify the code
//libadd.gopackage mainimport "C"//export addfunc add(left, right *C.char) *C.char { // bytes对应ctypes的c_char_p类型,翻译成C类型就是 char *指针 merge := C.GoString(left) + C.GoString(right) return C.CString(merge)}func main() {}
Re-compiling
go build -buildmode=c-shared -o libadd.so libadd.go
Referenced in Python
import ctypesadd = ctypes.CDLL('./libadd.so').add# 显式声明参数和返回的期望类型add.argtypes = [ctypes.c_char_p, ctypes.c_char_p]add.restype = ctypes.c_char_pleft = b"Hello"right = b"World"print(add(left, right))
Correct output Result:
b"HelloWorld"
In this way, a basic module is completed, as long as the input parameters and return the results of the data type processing, I only need to enrich the function of the processing logic, the Go module in the function of the internal implementation of Python is transparent, as long as the parameters are correct. More information about CGO, You can check golang.org for yourself.
Summarize
- The parameter transfer between Python and go, which needs to be converted to the corresponding C type when handling non-int
- cTYPES needs to explicitly declare the parameters of the DLL function and return the expected data type
- Note the difference between strings bytes and string in Python3
- The Go module needs to
//export
declare an externally callable
- The type of Go processing C is required to be explicitly converted