首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >指针字符串片(*[]字符串)的Cgo指针传递规则?

指针字符串片(*[]字符串)的Cgo指针传递规则?
EN

Stack Overflow用户
提问于 2018-08-17 08:11:19
回答 2查看 1K关注 0票数 2

我可以将*[]string从Go传递给C,然后将append传递给字符串片,还是它违反了指针传递规范

Go代码可以传递一个Go指针到C,条件是它所指向的Go内存不包含任何Go指针。

示例代码:

代码语言:javascript
复制
package main

/*
extern void go_callback(void*, char*);

static inline void callback(void* stringSliceGoPointer) {
    go_callback(stringSliceGoPointer, "foobar");
}
*/
import "C"

import (
    "fmt"
    "unsafe"
)

func main() {
    a := make([]string, 0)
    C.callback(unsafe.Pointer(&a)) 
    fmt.Println(a[0]) // outputs foobar
}

//export go_callback
func go_callback(stringSliceGoPointer unsafe.Pointer, msg *C.char) {
    slice := (*[]string)(stringSliceGoPointer)
    *slice = append(*slice, C.GoString(msg))
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-08-23 18:40:27

不允许将*[]string传递给C,因为指向的内存包含字符串,字符串包含指针。正如cgo文档所说(强调我的)

注意,一些Go类型的值是,除了该类型的零值之外,总是包含Go指针。对于字符串、片、接口、通道、映射和函数类型,这是正确的。

克服这一问题的一种方法是更间接地引用[]string,因此只有Go代码才知道其地址。例如:

代码语言:javascript
复制
package main

/*
extern void go_callback(int, char*);

static inline void callback(int stringSliceRef) {
    go_callback(stringSliceRef, "foobar");
}
*/
import "C"

import (
    "fmt"
)

// If you need to use these values concurrently,
// you'll need more code to protect this.
var stringSlices = make([][]string, 10)

func main() {
    C.callback(0) 
    fmt.Println(stringSlices[0][0]) // outputs foobar
}

//export go_callback
func go_callback(ref C.int, msg *C.char) {
    i := int(ref)
    stringSlices[i] = append(stringSlices[i], C.GoString(msg))
}
票数 2
EN

Stack Overflow用户

发布于 2018-08-21 06:47:01

不,这不可能。

有关go数据类型的进一步说明,请参阅

基本上,Go中的字符串类型如下所示。

代码语言:javascript
复制
str := "hello"

这是作为,

代码语言:javascript
复制
 str:                0xad234e3b:
 ┌──────────┬─┐      ┌───┬───┬───┬───┬───┐
 |0xad234e3b|5|  ┌──>|104|101|108|108|111| -->[5]byte
 └────┬─────┴─┘  |   └───┴───┴───┴───┴───┘
      └──────────┘

考虑一小片:

代码语言:javascript
复制
arr := string{"hi!","hello"}

此外,切片数据类型包含指针、长度、容量。

代码语言:javascript
复制
arr:                   0xd2b564c7:        0xad234e40:
┌──────────┬─┬─┐       ┌──────────┬─┐     ┌───┬───┬──┐
|0xd2b564c7|2|2|  ┌──> |0xad234e40|3|────>|104|105|33| -->[3]byte
└────┬─────┴─┴─┘  |    ├──────────┼─┤     └───┴───┴──┘
     └────────────┘    |0xad234e4b|5|──┐  0xad234e4b:
                       └──────────┴─┘  |  ┌───┬───┬───┬───┬───┐
                                       └─>|104|101|108|108|111| -->[5]byte
                                          └───┴───┴───┴───┴───┘

其中十六进制值表示地址。

存储实际数据的是一个[x]byte数组。

x表示数据(数组)的大小。

很明显,[]string本身包含许多(x)指针,而*[]string是另一个额外的指针。

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

https://stackoverflow.com/questions/51891020

复制
相关文章

相似问题

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