从 **char 到 python 列表
from **char to python list
问题已经解决,请看问题下方的回答
但是我终于发现把GO函数嵌入到Python中非常愚蠢。这种嵌入失败的主要原因是Go函数很难知道什么时候回收内存资源,从而导致内存泄漏。
目前,我认为将它们结合在一起的最佳方式可能是消息通信,例如袜子。
如果我的想法有误请指正。
原问题:
在C端,一个函数returns一个字符串数组(比如["i 0","i 1","i 2","i 3"]),类型是**char
.
在Python端,**char
输出被读入一个变量(比如cArray
),类型为POINTER(c_char_p)
我的问题:如何从 cArray
创建一个 python 列表?即获得pylist == ["i 0","i 1","i 2","i 3"]
我也想知道python里有没有取值操作,比如C里的*操作
代码示例如下:
C方(其实是Go)
package main
//#include <stdlib.h>
import "C"
import (
"unsafe"
)
//export TestLoad
func TestLoad(cstr *C.char) **C.char {
gostr := C.GoString(cstr)
goslice := []string{gostr, "i 0", "i 1", "i 2", "i 3"}
cArray := C.malloc(C.size_t(len(goslice)) * C.size_t(unsafe.Sizeof(uintptr(0))))
defer C.free(unsafe.Pointer(cArray))
temp := (*[1<<30 - 1]*C.char)(cArray)
for k, v := range goslice {
temp[k] = C.CString(v)
}
return (**C.char)(cArray)
}
func main() {
}
Python边
from ctypes import *
mylib = cdll.LoadLibrary("./mylib.so")
mylib.TestLoad.argtype = c_char_p
mylib.TestLoad.restype = POINTER(c_char_p) # ***Is it possible to have two or more restypes?***
pystr = "hello" # python str
b = pystr.encode("utf-8") # convert str to bytes
resp = mylib.TestLoad(b) # call CGo function, and get resp typed POINTER(c_char_p)
list_len = 5 # assume the length of list is known
'''
TODO
'''
顺便说一句,单个 C 或 CGO 函数 是否可以有两个或更多 returns?我试过了,编译失败。
感谢您的帮助。
解决方案:
C side (GO) -- defer C.free...
所在的那行要注释掉
package main
//#include <stdlib.h>
import "C"
import (
"fmt"
"unsafe"
)
//export TestLoad
func TestLoad(cstr *C.char) **C.char {
gostr := C.GoString(cstr)
fmt.Println("In Go: ", gostr)
goslice := []string{gostr, "i 0", "i 1", "i 2", "i 3"}
cArray := C.malloc(C.size_t(len(goslice)) * C.size_t(unsafe.Sizeof(uintptr(0))))
// defer C.free(unsafe.Pointer(cArray))
temp := (*[1<<30 - 1]*C.char)(cArray)
for k, v := range goslice {
temp[k] = C.CString(v)
}
return (**C.char)(cArray)
}
func main() {
}
Python 端 -- 修改:POINTER(c_char_p * 5),然后调用 resp.contents 访问每个 python 字节。有关来源,请参阅 Example #17。
from ctypes import *
mylib = cdll.LoadLibrary("./_mylib.so")
mylib.TestLoad.argtype = c_char_p
mylib.TestLoad.restype = POINTER(c_char_p*5)
pystr = "Hello, world!"
b = pystr.encode("utf-8")
resp = mylib.TestLoad(b)
'''**********************************'''
output = []
for seq in resp.contents:
s = seq.decode("utf-8")
output.append(s)
print(s,type(s))
print(output)
'''**********************************'''
出现新问题:
在这个例子中,注释 // defer C.free(unsafe.Pointer(cArray))
会导致 C 端内存泄漏吗?
问题已经解决,请看问题下方的回答
但是我终于发现把GO函数嵌入到Python中非常愚蠢。这种嵌入失败的主要原因是Go函数很难知道什么时候回收内存资源,从而导致内存泄漏。
目前,我认为将它们结合在一起的最佳方式可能是消息通信,例如袜子。
如果我的想法有误请指正。
原问题:
在C端,一个函数returns一个字符串数组(比如["i 0","i 1","i 2","i 3"]),类型是**char
.
在Python端,**char
输出被读入一个变量(比如cArray
),类型为POINTER(c_char_p)
我的问题:如何从 cArray
创建一个 python 列表?即获得pylist == ["i 0","i 1","i 2","i 3"]
我也想知道python里有没有取值操作,比如C里的*操作
代码示例如下:
C方(其实是Go)
package main
//#include <stdlib.h>
import "C"
import (
"unsafe"
)
//export TestLoad
func TestLoad(cstr *C.char) **C.char {
gostr := C.GoString(cstr)
goslice := []string{gostr, "i 0", "i 1", "i 2", "i 3"}
cArray := C.malloc(C.size_t(len(goslice)) * C.size_t(unsafe.Sizeof(uintptr(0))))
defer C.free(unsafe.Pointer(cArray))
temp := (*[1<<30 - 1]*C.char)(cArray)
for k, v := range goslice {
temp[k] = C.CString(v)
}
return (**C.char)(cArray)
}
func main() {
}
Python边
from ctypes import *
mylib = cdll.LoadLibrary("./mylib.so")
mylib.TestLoad.argtype = c_char_p
mylib.TestLoad.restype = POINTER(c_char_p) # ***Is it possible to have two or more restypes?***
pystr = "hello" # python str
b = pystr.encode("utf-8") # convert str to bytes
resp = mylib.TestLoad(b) # call CGo function, and get resp typed POINTER(c_char_p)
list_len = 5 # assume the length of list is known
'''
TODO
'''
顺便说一句,单个 C 或 CGO 函数 是否可以有两个或更多 returns?我试过了,编译失败。
感谢您的帮助。
解决方案:
C side (GO) -- defer C.free...
所在的那行要注释掉
package main
//#include <stdlib.h>
import "C"
import (
"fmt"
"unsafe"
)
//export TestLoad
func TestLoad(cstr *C.char) **C.char {
gostr := C.GoString(cstr)
fmt.Println("In Go: ", gostr)
goslice := []string{gostr, "i 0", "i 1", "i 2", "i 3"}
cArray := C.malloc(C.size_t(len(goslice)) * C.size_t(unsafe.Sizeof(uintptr(0))))
// defer C.free(unsafe.Pointer(cArray))
temp := (*[1<<30 - 1]*C.char)(cArray)
for k, v := range goslice {
temp[k] = C.CString(v)
}
return (**C.char)(cArray)
}
func main() {
}
Python 端 -- 修改:POINTER(c_char_p * 5),然后调用 resp.contents 访问每个 python 字节。有关来源,请参阅 Example #17。
from ctypes import *
mylib = cdll.LoadLibrary("./_mylib.so")
mylib.TestLoad.argtype = c_char_p
mylib.TestLoad.restype = POINTER(c_char_p*5)
pystr = "Hello, world!"
b = pystr.encode("utf-8")
resp = mylib.TestLoad(b)
'''**********************************'''
output = []
for seq in resp.contents:
s = seq.decode("utf-8")
output.append(s)
print(s,type(s))
print(output)
'''**********************************'''
出现新问题:
在这个例子中,注释 // defer C.free(unsafe.Pointer(cArray))
会导致 C 端内存泄漏吗?