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]))))
0

2 Answers 2

2

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.

Sign up to request clarification or add additional context in comments.

6 Comments

Re your last statement - "the overhead of calling into C is much bigger than allocating some memory and copying a string" - do you have any benchmarks to back that up?
@Not_a_Golfer In fact, I do. From a year ago: github.com/art4711/cgo_overhead If I get time I'll update it to 1.8.
Updated for 1.8. In 1.8 it's just 36 times slower instead of 92 times slower to make a cgo function call compared to a Go function call.
jesus! I wasn't aware it was so expensive. what causes this?
@Not_a_Golfer Many things. It needs to change the stack, many of the normal "this function doesn't use stack" optimizations are disabled, a bunch of stuff is run to make sure that we're not violating garbage collector rules (even when the C function takes no arguments), etc.
|
0

(*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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.