Skip to content

x/mobile: Issues converting Data to []byte in Swift #33745

Open
@SimplyDanny

Description

@SimplyDanny

What version of Go are you using (go version)?

$ go version
go version go1.12.9 darwin/amd64

Does this issue reproduce with the latest release?

Yes.

What operating system and processor architecture are you using (go env)?

go env Output
$ go env
GOARCH="amd64"
GOBIN=""
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOOS="darwin"
GOPROXY=""
GORACE=""
GOROOT="/usr/local/Cellar/go/1.12.9/libexec"
GOTMPDIR=""
GOTOOLDIR="/usr/local/Cellar/go/1.12.9/libexec/pkg/tool/darwin_amd64"
GCCGO="gccgo"
CC="clang"
CXX="clang++"
CGO_ENABLED="1"
GOMOD=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/gg/29c0x6691455vgkxwl2hrpgc0000gn/T/go-build354245371=/tmp/go-build -gno-record-gcc-switches -fno-common"

What did you do?

The Go source code

package gocode

import "fmt"

type Bytes struct {
	elements []byte
}

func NewBytes(elements []byte) *Bytes {
	fmt.Println("Constructor: ", elements)
	return &Bytes{elements: elements}
}

func (bytes *Bytes) GetElements() []byte {
	fmt.Println("Getter: ", bytes.elements)
	return bytes.elements
}

is compiled into an iOS framework using $GOPATH/bin/gomobile bind -target ios -o Gocode.framework gocode.
In a minimal iOS application there is the Swift code

import Foundation
import Gocode

let data = Data(repeating: 0, count: 8)
print("Data: \([UInt8](data))")
let bytes = GocodeNewBytes(data)!
print("Elements: \([UInt8](bytes.getElements()!))")
print("Data: \([UInt8](data))")

which can be compiled and run just fine. However, the printed values are not what I would expect.

What did you expect to see?

Data: [0, 0, 0, 0, 0, 0, 0, 0]
Constructor:  [0 0 0 0 0 0 0 0]
Getter:  [0 0 0 0 0 0 0 0]
Elements: [0, 0, 0, 0, 0, 0, 0, 0]
Data: [0, 0, 0, 0, 0, 0, 0, 0]

What did you see instead?

Data: [0, 0, 0, 0, 0, 0, 0, 0]
Constructor:  [0 0 0 0 0 0 0 0]
Getter:  [184 144 247 1 1 0 0 0]
Elements: [184, 144, 247, 1, 1, 0, 0, 0]
Data: [0, 0, 0, 0, 0, 0, 0, 0]

The data is correctly passed to the Go functions and back to Swift, but internally constructing the Bytes object it somehow changes. If I rewrite the constructor in Go as

func NewBytes(elements []byte) *Bytes {
	fmt.Println("Constructor: ", elements)
	tmp := make([]byte, len(elements))
	copy(tmp, elements)
	return &Bytes{elements: tmp}
}

it works as anticipated. I'm not sure whether this is a bug or expected but unpleasant behavior due to Go's and Swift's handling of values and references. If the latter is true I really have no idea how to solve this issue on the Swift side in order to utilize Go libraries using []byte at any interface function.

Metadata

Metadata

Assignees

No one assigned

    Labels

    ExpertNeededNeedsInvestigationSomeone must examine and confirm this is a valid issue and not a duplicate of an existing one.mobileAndroid, iOS, and x/mobile

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions