首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在golang中访问C数组

在golang中访问C数组
EN

Stack Overflow用户
提问于 2018-11-10 11:44:53
回答 2查看 2.5K关注 0票数 3

我有两个文件,module.gotest.py。我的目标是加速在python中完成的一些计算,但是在go中有一个访问整数数组的问题。

module.go

代码语言:javascript
运行
复制
package main

import "C"

//export Example
func Example(testArray []C.int) C.int {
    return testArray[2]
}

func main() {}

和python中的简单测试文件:

代码语言:javascript
运行
复制
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文件之后,我得到了:

代码语言:javascript
运行
复制
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不同,但我无法找到任何教程,如何在没有恐慌的情况下访问它的值。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-11-10 19:27:02

这是一种惯用的、高效的Go解决方案(避免反射)。

module.go

代码语言:javascript
运行
复制
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

代码语言:javascript
运行
复制
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))

输出:

代码语言:javascript
运行
复制
$ go build -buildmode=c-shared -o gomodule.so module.go
$ python test.py
4
$ 
票数 8
EN

Stack Overflow用户

发布于 2018-11-10 12:54:40

C中的数组不能自动抛到Go中的片中。注意,在Go中,片有两个部分:长度和指向支持数据的指针。

因此,您必须手动从指针创建切片。

代码语言:javascript
运行
复制
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导出函数,如下所示:

代码语言:javascript
运行
复制
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)

上面的示例应该打印数组的第四个索引元素。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53238602

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档