x/mobile: go interfaces become objc protocol and interface with the same name #35003
Labels
Milestone
Comments
Ugh nevermind on this, it was my mistake. The objc protocol can be used directly in swift already by appending the The generated x.h objc header @protocol Machine
@end
@interface Machine
@end class MyMachine: MachineProtocol {
} Now everything works fine, I can pass an instance of MyMachine directly to go. I also see that the medium blogpost I referenced discuss this exact point, but I glossed over it before. It would be useful if the gomobile documentation referenced this point perhaps. |
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
What version of Go are you using (
go version
)?Does this issue reproduce with the latest release?
The go version is irrelevant, as this is a problem with gomobile.
What operating system and processor architecture are you using (
go env
)?go env
OutputReport (with a fix)
gomobile bind -target ios
does not allow one to declare an interface in go, subclass that interface in swift, and then pass an instance of that subclass to go. When the instance is passed to go a runtime error occurs:Essentially my code is
x.go
x.swift
The exception is really thrown in the generated code for
Run
when the incoming objc object is converted to a refnum.As far as I can tell this is because
gostuffMachine
has two declarations, one as a@protocol
and one as an@interface
When the swift side goes to implemet
Machine
it picks up the one declared as an interface rather than the protocol (I'm not an objc/swift expert so I don't understand the subtleties here). In any case, the interface version has aninitWithRef
constructor that only the go code knows how to call when aMachine
instance is constructed from go. When swift creates a subclass ofMachine
it does not call theinitWithRef
constructor, so_ref
is null, and ultimately when the C code gets toThis condition is true, due to the interface inheriting from
goSeqRefInterface
, and then the C code dies at trying to invokego_seq_go_to_refnum(machine_proxy.ref)
.The fix I have made so far is to append the word
Protocol
to the protocols generated by genobjc.go. Essentially this patch:This question was asked on stack overflow: https://stackoverflow.com/questions/50815664/gomobile-binding-callbacks-for-objc
and that question was also added to the end of an old gomobile issue but left unaddressed: #17102 (comment)
Anyway, I was initially quite confused about the default behavior of gomobile. Based on the following blog post I had assumed this would all work out fine: https://medium.com/@matryer/tutorial-calling-go-code-from-swift-on-ios-and-vice-versa-with-gomobile-7925620c17a4
In fact that blog post does exactly what I'm trying to accomplish, and even says the protocol name ends with
Protocol
, yet clearly the genobjc.go file in gomobile does not name protocols this way. The naming of protocols seems to have been done in bf2ca7a93b02169b6f8c221ba13b22919a728994, from 2015.I have not tested this change with pure objc projects, but I don't think it breaks any functionality there (except for changing naming, same as in swift).
If you need a small test case I can produce one.
The text was updated successfully, but these errors were encountered: