我有一个名为test.go
的模块,它包含两个接受字符串类型的简单Go函数:
package main
import (
"fmt"
"C"
)
//export TestConcat
func TestConcat(testArg string, testArg2 string) (string) {
retval := testArg + testArg2
return retval
}
//export TestHello
func TestHello(testArg string) {
fmt.Println("%v\n", testArg)
}
func main(){}
我将它编译为一个与go build -o test.so -buildmode=c-shared test.go
共享的库
然后我有一个名为test.py
的Python模块
import ctypes
from ctypes import cdll
test_strings = [
"teststring1",
"teststring2"
]
if __name__ == '__main__':
lib = cdll.LoadLibrary("./test.so")
lib.TestConcat.argtypes = [ctypes.c_wchar_p, ctypes.c_wchar_p]
lib.TestHello.argtypes = [ctypes.c_wchar_p]
for test_string in test_strings:
print(
lib.TestConcat("hello", test_string)
)
lib.TestHello(test_string)
然后我运行test.py
并得到一个严重的错误
runtime: out of memory: cannot allocate 279362762964992-byte block (66781184 in use)
fatal error: out of memory
我试图用ctypes.c_wchar_p
来包装这些参数,但没有用
我做错了什么?具体来说,如何与Python中接受字符串参数的Go函数交互
Go的
string
类型实际上类似于这就是
Test{Hello|Concat}
实际上期望的不是一对指针,而是一对struct
类型的值。换言之,
cgo
执行的魔力刚好足以让网关调用从Go到C再返回,但它不执行值的自动转换您有两个选择:
如果可能的话,请从
ctypes
绑定显式地处理此问题。编译包时,
cgo
生成一个头文件,其中包含表示Go字符串的结构的C定义;你可以马上用使导出到C的函数与C的“类型系统”兼容。} and ^{} 。
为此,
cgo
提供了helper functions ^{基本上,您可以这样定义API:
请注意以下几点注意事项:
a
和b
指向的内存块,然后消耗两倍的内存以生成连接的字符串,然后再次复制结果字符串的内存以生成返回的指针。注意,如果您试图将一大块Go代码导出到C,那么这种方法是很好的,这样这些分配就比该块所做的任何事情都要小李>
*C.char
与C中的*char
相同,因此字符串应该以NUL结尾;如果不是,请使用C.GoStringN
李>C.CString
分配的每个内存块都必须通过调用C.free
来释放。这里有一个转折:C.free
基本上是从libc
中链接的free()
调用free()
的薄垫片,因此,如果您可以保证完整的产品(完全加载到内存中并使用动态链接器链接的代码)只有一个libc
链接的副本,那么您可以调用free()
从Go代码中对C.Cstring
的调用产生的内存块上的非Go代码李>还有几个随机指针:
<> Li >我不精通Python的{{CD5}},但我推测使用{{c+24}}是不正确的:在C(和C++,fWIW)^ {CD25}}是一种表示单个< EM >固定大小的“宽字符”,这是通常 aUCS-2/UTF-16代码点,并且Go的字符串不包括这些字符串,它们可以包含任意字节,当它们用于包含Unicode文本时,使用UTF-8进行编码,这是一种多字节编码(单个Unicode代码点可以由字符串中的1到4个字节表示)。- 在开始这个项目之前,请完整地阅读the docs on ^{
} 。真的,请吧李>
在这两种情况下,
wchar_t
不能用于UTF-8(实际上是many seasoned devs beleive it's an abomination)李>相关问题 更多 >
编程相关推荐