在golang中访问C数组
Accessing C array in golang
我有两个文件,module.go
和 test.py
。我的目标是加快在 python 中完成的一些计算,但在访问整数数组时遇到问题。
module.go
package main
import "C"
//export Example
func Example(testArray []C.int) C.int {
return testArray[2]
}
func main() {}
和python中的简单测试文件:
from ctypes import *
# Load compiled go module
lib = cdll.LoadLibrary("./gomodule.so")
# We are passing an array of 256 elements and recieving integer
lib.Example.argtypes = [c_int * 256]
lib.Example.restype = c_int
pyarr = [x for x in range(256)]
# Make C array from py array
arr = (c_int * len(pyarr))(*pyarr)
print lib.Example(arr)
使用 go build -buildmode=c-shared -o gomodule.so module.go
编译 go 模块并启动 python 文件后,我得到:
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x12 pc=0x7fb18b6e688c]
goroutine 17 [running, locked to thread]:
main.Example(...)
/home/metro/go/src/github.com/golubaca/carinago/module.go:7
main._cgoexpwrap_53c1c00d0ad3_Example(0xa, 0x7fff33a2eac0, 0x7fff33a2ea70, 0x722a921de6cae100)
_cgo_gotypes.go:47 +0x1c
Aborted (core dumped)
我知道 C 数组与 Go 不同,但找不到任何教程如何在没有恐慌的情况下访问它的值。
C 中的数组无法自动转换为 Go 中的切片。请注意,在 Go 中,切片有两个部分:长度和指向支持数据的指针。
因此您必须从指针手动创建切片。
package main
import (
"C"
"reflect"
"unsafe"
)
//export Example
func Example(carr *C.int, size int, idx int) C.int {
// Build the slice manually using unsafe
var slice []C.int
header := (*reflect.SliceHeader)(unsafe.Pointer(&slice))
header.Cap = size
header.Len = size
header.Data = uintptr(unsafe.Pointer(carr))
return slice[idx]
}
func main() {}
然后您可以在 python 代码中调用 Go 导出函数,例如:
from ctypes import *
# Load compiled go module
lib = cdll.LoadLibrary("./gomodule.so")
# We are passing an array of 256 elements and recieving integer
lib.Example.argtypes = [c_int * 256]
lib.Example.restype = c_int
pyarr = [x for x in range(256)]
# Make C array from py array
arr = (c_int * len(pyarr))(*pyarr)
print lib.Example(arr, len(arr), 4)
上面的例子应该打印数组的第 4 个索引元素
这是惯用的、高效的 Go 解决方案(避免反射)。
module.go
:
package main
import "C"
import "unsafe"
//export Example
func Example(cArray *C.int, cSize C.int, i C.int) C.int {
gSlice := (*[1 << 30]C.int)(unsafe.Pointer(cArray))[:cSize:cSize]
return gSlice[i]
}
func main() {}
test.py
:
from ctypes import *
# Load compiled go module
lib = cdll.LoadLibrary("./gomodule.so")
# We are passing an array of 256 elements and receiving an integer
lib.Example.argtypes = [c_int * 256]
lib.Example.restype = c_int
pyarr = [x for x in range(256)]
# Make C array from py array
arr = (c_int * len(pyarr))(*pyarr)
print(lib.Example(arr, len(arr), 4))
输出:
$ go build -buildmode=c-shared -o gomodule.so module.go
$ python test.py
4
$
我有两个文件,module.go
和 test.py
。我的目标是加快在 python 中完成的一些计算,但在访问整数数组时遇到问题。
module.go
package main
import "C"
//export Example
func Example(testArray []C.int) C.int {
return testArray[2]
}
func main() {}
和python中的简单测试文件:
from ctypes import *
# Load compiled go module
lib = cdll.LoadLibrary("./gomodule.so")
# We are passing an array of 256 elements and recieving integer
lib.Example.argtypes = [c_int * 256]
lib.Example.restype = c_int
pyarr = [x for x in range(256)]
# Make C array from py array
arr = (c_int * len(pyarr))(*pyarr)
print lib.Example(arr)
使用 go build -buildmode=c-shared -o gomodule.so module.go
编译 go 模块并启动 python 文件后,我得到:
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x12 pc=0x7fb18b6e688c]
goroutine 17 [running, locked to thread]:
main.Example(...)
/home/metro/go/src/github.com/golubaca/carinago/module.go:7
main._cgoexpwrap_53c1c00d0ad3_Example(0xa, 0x7fff33a2eac0, 0x7fff33a2ea70, 0x722a921de6cae100)
_cgo_gotypes.go:47 +0x1c
Aborted (core dumped)
我知道 C 数组与 Go 不同,但找不到任何教程如何在没有恐慌的情况下访问它的值。
C 中的数组无法自动转换为 Go 中的切片。请注意,在 Go 中,切片有两个部分:长度和指向支持数据的指针。
因此您必须从指针手动创建切片。
package main
import (
"C"
"reflect"
"unsafe"
)
//export Example
func Example(carr *C.int, size int, idx int) C.int {
// Build the slice manually using unsafe
var slice []C.int
header := (*reflect.SliceHeader)(unsafe.Pointer(&slice))
header.Cap = size
header.Len = size
header.Data = uintptr(unsafe.Pointer(carr))
return slice[idx]
}
func main() {}
然后您可以在 python 代码中调用 Go 导出函数,例如:
from ctypes import *
# Load compiled go module
lib = cdll.LoadLibrary("./gomodule.so")
# We are passing an array of 256 elements and recieving integer
lib.Example.argtypes = [c_int * 256]
lib.Example.restype = c_int
pyarr = [x for x in range(256)]
# Make C array from py array
arr = (c_int * len(pyarr))(*pyarr)
print lib.Example(arr, len(arr), 4)
上面的例子应该打印数组的第 4 个索引元素
这是惯用的、高效的 Go 解决方案(避免反射)。
module.go
:
package main
import "C"
import "unsafe"
//export Example
func Example(cArray *C.int, cSize C.int, i C.int) C.int {
gSlice := (*[1 << 30]C.int)(unsafe.Pointer(cArray))[:cSize:cSize]
return gSlice[i]
}
func main() {}
test.py
:
from ctypes import *
# Load compiled go module
lib = cdll.LoadLibrary("./gomodule.so")
# We are passing an array of 256 elements and receiving an integer
lib.Example.argtypes = [c_int * 256]
lib.Example.restype = c_int
pyarr = [x for x in range(256)]
# Make C array from py array
arr = (c_int * len(pyarr))(*pyarr)
print(lib.Example(arr, len(arr), 4))
输出:
$ go build -buildmode=c-shared -o gomodule.so module.go
$ python test.py
4
$