Python调用Golang代码的那些细节缩

  1.  字符串传递

    字符串在从Python传给Golang的时候,跟传递给C是一样的,需要用ctypes.cast()将字符串末尾添上终止符保护起来

buffer = ctypes.create_string_buffer("A String".encode("utf-8"))
string_c_array = ctypes.cast(ctypes.pointer(buffer), ctypes.c_char_p)
 在对应的Golang代码中,函数的入参应当是 dataString *C.char这样子的,但是这样还不能直接使用,需要在接收之后进行一次转换
goString := C.GoString(dataString)
fmt.Printf("go string = %s\n", goString)

2.  数字传递

    传递int是最简单的,Python里的int就可以直接使用,对应Golang代码中,函数的入参应当是`num C.int`,可以直接使用,不需要做什么转换

3.  字符串数组传递

    Python代码中有一个字符串,例如:item_ids = [“Item1”, “Item2”, “Item3”],想要传给Golang函数,需要用两个参数,一个是数组的指针,一个是数组的长度,对应的argtypes分别是ctypes.POINTER(ctypes.c_char_p)和ctypes.c_int,可以简单的理解c_char_p就是string类型即可。

一个简单的样例如下:


item_ids = ["Item1", "Item2", "Item3"]
item_id_array = np.array(item_ids, dtype=np.str_)
item_id_c_array = (ctypes.c_char_p * len(item_id_array))()
for i, item_id in enumerate(item_id_array):
    buffer = ctypes.create_string_buffer(item_id.encode("utf-8"))
    item_id_c_array[i] = ctypes.cast(ctypes.pointer(buffer), ctypes.c_char_p)
item_id_size = len(item_ids)

 在Golang函数中,使用两个参数接收,分别是ids **C.char, size C.int对应Python中的item_id_c_array和item_id_size,在Golang中使用的时候有一点细节需要注意


stringPointers := (*[1<<30 - 1]*C.char)(unsafe.Pointer(ids))[:size:size]
for _, str := range stringPointers {
    fmt.Println(C.GoString(str))
}

这样便可以取出来Python传过来的数组内容了。

4.  protobuf超大结构体的传递

直接把protobuf的对象给序列化了,变成字符串传递,在Python中


examples_proto = examples.SerializeToString()

在Golang中使用方法是:


var example pb.Example
err := proto.Unmarshal([]byte(C.GoString(examplesIn)), &example)

5.  把Golang的结构体传给Python

    说完了Python传给Golang,在Golang代码计算好了之后,也需要把结果返回给Python

一个简单的方法就是,在Golang里面给转成json字符串,再在Python中解析一下即可


jsonObj, err := json.Marshal(dataObj)
if err != nil {
    fmt.Errorf("Json Marshal DataObject Failed with error %s\n", err.Error())
    panic(err)
}
return C.CString(string(jsonObj))

6. 终极优雅方案

Python调用Golang代码的那些细节插图

链接:https://juejin.cn/post/7301281320667316259

(版权归原作者所有,侵删)

本文链接:https://www.yunweipai.com/44371.html

(完)