how can I get the data pointer of a string variable in go?

huangapple go评论75阅读模式
英文:

how can I get the data pointer of a string variable in go?

问题

我想要获取一个字符串变量的数据指针(类似于C++中的string::c_str()),以便将其传递给一个C函数,但我发现这种方法不起作用:

package main

/*
#include <stdio.h>
void Println(const char* str) {printf("%s\n", str);}
*/
import "C"

import (
    "unsafe"
)

func main() {
    s := "hello"
    C.Println((*C.char)(unsafe.Pointer(&(s[0]))))
}

编译错误信息是:'cannot take the address of s[0]'。我担心这样做会导致不必要的内存分配。有没有更好的方法来获取数据指针?

C.Println((*C.char)(unsafe.Pointer(&([]byte(s)[0]))))
英文:

I want to get the data pointer of a string variable(like string::c_str() in c++) to pass to a c function and I found this doesn't work:

package main

/*
#include &lt;stdio.h&gt;
void Println(const char* str) {printf(&quot;%s\n&quot;, str);}
*/
import &quot;C&quot;

import (
    &quot;unsafe&quot;
)

func main() {
    s := &quot;hello&quot;
    C.Println((*C.char)(unsafe.Pointer(&amp;(s[0]))))
}

Compile error info is: 'cannot take the address of s[0]'.
This will be OK I but I doubt it will cause unneccesary memory apllying. Is there a better way to get the data pointer?

C.Println((*C.char)(unsafe.Pointer(&amp;([]byte(s)[0]))))

答案1

得分: 2

有一种方法可以在不复制的情况下从Go字符串获取底层数据到C中。它不会作为C字符串工作,因为它不是C字符串。即使你设法提取指针,你的printf也不会起作用,即使有时它可能会工作。Go字符串不是C字符串。在Go使用更多的libc时,它们曾经是为了兼容性而存在,但现在不再是了。

只需按照cgo手册的指示使用C.CString。如果你为了效率而奋斗,那么不使用cgo会获得更大的收益,因为调用C的开销比分配一些内存和复制一个字符串要大得多。

英文:

There are ways to get the underlying data from a Go string to C without copying it. It will not work as a C string because it is not a C string. Your printf will not work even if you manage to extract the pointer even if it happens to work sometimes. Go strings are not C strings. They used to be for compatibility when Go used more libc, they aren't anymore.

Just follow the cgo manual and use C.CString. If you're fighting for efficiency you'll win much more by just not using cgo because the overhead of calling into C is much bigger than allocating some memory and copying a string.

答案2

得分: 0

(*reflect.StringHeader)(unsafe.Pointer(&sourceTail)).Data

在Go语言中,字符串不以空字符结尾,因此在传递给对应的C函数时,你应该始终传递DataLen参数。C标准库中有一系列函数用于处理这种类型的字符串,例如,如果你想用printf格式化它们,格式说明符应该是%.*s而不是%s,并且你需要在参数列表中同时传递长度和指针。

英文:

(*reflect.StringHeader)(unsafe.Pointer(&amp;sourceTail)).Data

Strings in go are not null terminated, therefore you should always pass the Data and the Len parameter to the corresponding C functions. There is a family of functions in the C standard library to deal with this type of strings, for example if you want to format them with printf, the format specifier is %.*s instead of %s and you have to pass both, the length and the pointer in the arguments list.

huangapple
  • 本文由 发表于 2017年2月27日 15:20:28
  • 转载请务必保留本文链接:https://go.coder-hub.com/42479895.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定