英文:
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 <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]))))
}
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(&([]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函数时,你应该始终传递Data
和Len
参数。C标准库中有一系列函数用于处理这种类型的字符串,例如,如果你想用printf格式化它们,格式说明符应该是%.*s
而不是%s
,并且你需要在参数列表中同时传递长度和指针。
英文:
(*reflect.StringHeader)(unsafe.Pointer(&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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论