【问题标题】:How to use extern c strings in cgo如何在cgo中使用extern c字符串
【发布时间】:2021-04-22 07:49:11
【问题描述】:

我正在尝试在 go 程序中使用 c 库中的 c 字符串,但出现错误:

a.h文件:

extern const char *s[];

a.c文件:

const char *s[] = {"a", "b", "c"};

我把这两个文件编译成liba.a

main.go文件:

package main

// #cgo LDFLAGS: -L${SRCDIR} -la
// #include"a.h"
import "C"
import "fmt"

func main() {
        x := 1
        fmt.Println(x)
        fmt.Println(len(C.s))
        fmt.Println(C.GoString(C.s[x]))
}

然后我用命令运行代码

go run main.go

我得到了错误:

panic: runtime error: index out of range [0] with length 0

如何解决?谢谢

go 版本:go version go1.15.7 linux/amd64

【问题讨论】:

  • 不要在标题中添加标签。
  • 你如何建立你的存档文件?为什么不使用对象(.o
  • 我使用命令gcc -c -o a.o a.c && ar rcs liba.a a.o 构建存档文件。我面临的问题是在go中使用c接口。如果我使用目标文件,则要链接的文件太多。

标签: go cgo


【解决方案1】:

C 中的数组不是由 cgo 透明处理的。

有所谓的惯用 Go 将 C 内存映射到 Go 可以自然操作的东西。这是一个工作示例 (main.go):

package main

import (
    "fmt"
    "unsafe"
)

// #cgo LDFLAGS: -L${SRCDIR} -la
// #include "./a.h"
import "C"

func main() {
    x := 1
    fmt.Println(x)
    fmt.Println(len(C.s)) // Note, Go has no idea so it says 0.

    cStr := (*[1 << 30]*C.char)(unsafe.Pointer(&C.s))[x]

    fmt.Println(C.GoString(cStr))
}

关键部分是(*[1 &lt;&lt; 30]*C.char)(unsafe.Pointer(&amp;C.s))。这意味着将&amp;C.s 解释为一个非常大的恒定大小数组(“对任何人都足够大”...),但只从中提取感兴趣的元素[x]

unsafe.Pointer() 的使用应该是一个警告,即超出实际 C 数组的末尾会产生不可预知的结果。确实,它可能会使程序崩溃。

【讨论】:

    猜你喜欢
    • 2014-10-09
    • 2021-11-15
    • 1970-01-01
    • 2023-02-24
    • 1970-01-01
    • 2010-10-04
    • 2021-05-23
    • 2016-12-25
    • 2012-05-12
    相关资源
    最近更新 更多