- edited description
Corruption issue when passing GoString from C to Go via cgo
I'm having an issue calling Go functions from C. Arguments passed to my Go function are being corrupted, but only when a GoString is the first argument to the function. This appears to be ios-specific, as I can't reproduce on OS X with stock Go 1.4.
See attached Xcode project (for iOS) and simple Go program (for OS X).
When running GoBugReportIOS on my iPhone 6 and iPhone 6 Plus, it crashes because it gets the wrong value for the function pointer:
Hello from Go! I'm in func main()!
Hello from Objective C! I'm in int iosmain()!
Go: (no path) Calling 91d9 ( b16e4 ) - 37337 ( 726756 )
C: Calling 91d9 / b16e4 - as pointer: 0x91d9
Go: (path=ok) Calling 91d900000000 ( b16e400000000 ) - 160361193930752 ( 3121393252171776 )
C: Calling 91d900000000 / b16e400000000 - as pointer: 0x0
The same problem does not exist on OS X:
$ ./GoBugReportOSX
Hello from Go! I'm in func main()!
Go: (no path) Calling 4000a40 ( 40955d0 ) - 67111488 ( 67720656 )
C: Calling 4000a40 / 40955d0 - as pointer: 0x4000a40
C: Successfully called callMeFromGo with arg 0x40955d0 - useMeForData
Go: (path=ok) Calling 4000a40 ( 40955d0 ) - 67111488 ( 67720656 )
C: Calling 4000a40 / 40955d0 - as pointer: 0x4000a40
C: Successfully called callMeFromGo with arg 0x40955d0 - useMeForData
Comments (8)
-
reporter -
repo owner Interesting. I will take a look. Thanks for the report.
-
repo owner It has something to do with function argument alignments.
I'm wondering if Obj-C has different function argument alignment rules (for 64-bit integer) than C.
-
reporter I can test tomorrow. Should be pretty easy to confirm, just rename main.c to main.m in the OS X folder and rebuild.
-
repo owner I think I found the problem.
You've used _cgo_export.h generated for host, and the type of GoInt is different on ARM and x86_64.
Essentially Go thinks GoString is two words (one pointer and one 32-bit length), but the Obj-C code thinks the GoString structure is made of one pointer and one 64-bit integer, this mismatches causes the function argument to be incompatible.
Please use _cgo_export.h generated with GOARCH=arm cgo (the usual way is to use
GOARCH=arm CGO_ENABLED=1 go build -work main.go
, and then copy the correct _cgo_export.h from the displayed $WORK) -
reporter Wow! Yes you're right! I wonder if _cgo_export.h should include a header explaining what arch it was generated for. Or even an #ifdef!
-
repo owner I will see what I can do for Go 1.5. Thanks for confirmation.
-
repo owner - changed status to resolved
_cgo_export.h generated Go 1.5 will complain if used for the wrong architecture. Closing as fixed.
- Log in to comment