Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cmd/cgo: provide a way to pass a Go string directly to C code #6907

Closed
gopherbot opened this issue Dec 6, 2013 · 6 comments
Closed

cmd/cgo: provide a way to pass a Go string directly to C code #6907

gopherbot opened this issue Dec 6, 2013 · 6 comments
Labels
early-in-cycle A change that should be done early in the 3 month dev cycle. FrozenDueToAge NeedsFix The path to resolution is known, but the work has not been done.
Milestone

Comments

@gopherbot
Copy link

by james@jamesh.id.au:

What steps will reproduce the problem?

I'm writing a wrapper for a C++ API that takes with std::string arguments.  In order to
interface with it via CGo, I call it through a shim API.

Ideally, I would like to build the std::string instances directly from the Go string in
the shim layer, but there doesn't seem to be a way to declare the shim function such
that it can take the Go string directly.

I can't use the GoString declaration in _cgo_export.h, and declaring the GoString struct
type myself generates an error (for good reason).

What is the expected output?

A way to declare my function so that it can accept a Go string directly.

What do you see instead?

There is no way to do the above, and I need to convert the string to a *C.char (which
causes an unneeded allocation and two extra Go->C transitions for the allocation and
release of the memory).


Which compiler are you using (5g, 6g, 8g, gccgo)?

6g

Which operating system are you using?

Linux (amd64)

Which version are you using?  (run 'go version')

1.2
@rsc
Copy link
Contributor

rsc commented Mar 3, 2014

Comment 1:

You can certainly do unsafe things already to get at the string memory. If you must, do
that. I don't believe that we will support this more easily, because a C++ string is
mutable and a Go string is not.

Status changed to WorkingAsIntended.

@gopherbot
Copy link
Author

Comment 2 by james@jamesh.id.au:

I'm not after a way to alter the Go string.  I've worked with enough language bindings
to know not to screw around with the runtime like that.
Rather, if I'm going to have to make a copy of the string to call my API, it seems
wasteful to create an intermediate copy with C.GoString rather than just using the
original Go string as source for the copy.
Similarly, for API calls that can deal with constant string data plus a length, it'd be
nice to be able to do so without a copy.
If there are existing ways to handle this kind of thing, would it be possible to
document them?

@ianlancetaylor
Copy link
Contributor

I think this is a reasonable thing to do. We should provide a way for the C code to get a pair of a const char * and length, to make it straightforward to pass a Go string to C code without a copy. Yes, they can break things horribly, but there are many ways to do that.

@rsc
Copy link
Contributor

rsc commented May 17, 2016

I agree this is reasonable, but it's too late in the cycle to do it now.

@rsc rsc modified the milestones: Go1.8, Go1.7 May 17, 2016
@quentinmit quentinmit added the NeedsFix The path to resolution is known, but the work has not been done. label Oct 10, 2016
@rsc rsc modified the milestones: Go1.9Early, Go1.8 Oct 21, 2016
@bradfitz bradfitz modified the milestones: Go1.9Early, Go1.10Early May 3, 2017
@bradfitz bradfitz added early-in-cycle A change that should be done early in the 3 month dev cycle. and removed early-in-cycle A change that should be done early in the 3 month dev cycle. labels Jun 14, 2017
@bradfitz bradfitz modified the milestones: Go1.10Early, Go1.10 Jun 14, 2017
@gopherbot
Copy link
Author

Change https://golang.org/cl/70890 mentions this issue: cmd/cgo: permit passing string and []byte directly between Go and C

@bcmills
Copy link
Contributor

bcmills commented Oct 25, 2017

We should provide a way for the C code to get a pair of a const char * and length, to make it straightforward to pass a Go string to C code without a copy.

It occurs to me that the combination of runtime.KeepAlive and reflect.StringHeader already makes that possible today (provided that one is willing to ignore the “cannot be used safely or portably” caveat of reflect.StringHeader):

func asPtrAndLength(s string) (*C.char, int) {
	addr := &s
	hdr := (*reflect.StringHeader)(unsafe.Pointer(addr))

	p := (*C.char)(unsafe.Pointer(hdr.Data))
	n := hdr.Len

	// reflect.StringHeader stores the Data field as a uintptr, not a pointer,
	// so ensure that the string remains reachable until the uintptr is converted.
	runtime.KeepAlive(addr)

	return p, n
}

@golang golang locked and limited conversation to collaborators Nov 15, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
early-in-cycle A change that should be done early in the 3 month dev cycle. FrozenDueToAge NeedsFix The path to resolution is known, but the work has not been done.
Projects
None yet
Development

No branches or pull requests

6 participants