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

Comments

@gopherbot
Copy link

commented Dec 6, 2013

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

This comment has been minimized.

Copy link
Contributor

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

This comment has been minimized.

Copy link
Author

commented Mar 4, 2014

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

This comment has been minimized.

Copy link
Contributor

commented Feb 2, 2016

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.

@ianlancetaylor ianlancetaylor reopened this Feb 2, 2016

@ianlancetaylor ianlancetaylor added this to the Go1.7 milestone Feb 2, 2016

@ianlancetaylor ianlancetaylor self-assigned this Feb 2, 2016

@rsc

This comment has been minimized.

Copy link
Contributor

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 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 modified the milestones: Go1.10Early, Go1.10 Jun 14, 2017

@gopherbot

This comment has been minimized.

Copy link
Author

commented Oct 14, 2017

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

@bcmills

This comment has been minimized.

Copy link
Member

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
}

@gopherbot gopherbot closed this in 918396b Nov 15, 2017

@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.
Projects
None yet
6 participants
You can’t perform that action at this time.