Closed dirkwhoffmann closed 4 months ago
Proof-of-concept. Old code:
@IBAction func pauseAction(_ sender: Any!) {
if c64.running { c64.pause() }
}
@IBAction func continueAction(_ sender: Any!) {
if c64.paused { try? c64.run() }
}
@IBAction func stopAndGoAction(_ sender: Any!) {
c64.stopAndGo()
}
c64
is the existing ObjC proxy. The Swift GUI now contains a variable v64
which links directly to the C++ core (reference copied from the existing proxy).
Now, the old code can be replaced by this one, which proves the concept working:
@IBAction func pauseAction(_ sender: Any!) {
if v64.isRunning() { v64.pause() }
}
@IBAction func continueAction(_ sender: Any!) {
if v64.isPaused() { v64.run() }
}
@IBAction func stopAndGoAction(_ sender: Any!) {
v64.stopAndGo()
}
It's also possible to expose some C++ functions as properties to Swift (one could then write v64.isPaused
instead of v64.isPaused()
etc.), but I haven't looked into this yet.
Bummer! This makes the new feature useless for me.
Swift can interoperate with C++ code that throws exceptions. However, Swift does not support catching C++ exceptions. Instead, the running program terminates with a fatal error when a C++ exception that’s not caught by C++ code reaches Swift code.
Update: Because Swift cannot communicate with the C++ core directly due to the lack of exception support, I tried to port the ObjC proxy to Swift, utilizing the same exception passing trick as I did in the ObjC proxy. At the beginning, this worked well. However, after adding more and more functions, Swift build times were skyrocketing, reaching several minutes to compile.
Bottom line: Swift / C++ interop still seems to be in an early beta state, which makes it pretty unusable in larger real-life projects. Apple's marketing videos are brilliant, though. Good job there, as usual.
During WWDC 2023, Apple announced that Swift can interact directly with C++:
https://developer.apple.com/videos/play/wwdc2023/10172 https://www.swift.org/documentation/cxx-interop/
This is an excellent opportunity to trash the ObjC layer. The layer is a large portion of code, with the sole purpose of bridging the gap between Swift and C++ (originally, Swift could only talk to C).
As always, it's not as simple as they propose in the video, but I finally reached the point where I think I know what has to be done.
Here is the plan:
VirtualC64
to the Swift code and initialize it with the reference created inside the ObjC proxy. Now, the C++ core can either be accessed via the existing ObjC proxy or the Swift reference.A lot of preliminary work has already been done:
SWIFT_UNSAFE_REFERENCE
. Otherwise, the VirtualC64 class would be translated to a Swift struct having "value type".enum_long
stuff has been removed. It defined enums differently on both the Swift side and the C++ side, because I didn't know how to serialize real C enum's in a generic way. This has been solved and both side see enums as standard C enums now.