Using/calling Swift things (at least functions) from C today?

Its incredibly easy to get C things into Swift, but getting Swift things (at least functions) into C is a whole different story.

How would one go about that today? I am building an application that currently uses nothing but plain C. I love C! But at the same time I want it to work well with macOS and iOS. It's always possible to rewrite the entrypoint in Swift, but holding on to this one-way connection will introduce... Suffering... In the future.

The main concern here is Metal support. That's a must. Getting this working on my TV isn't as important :). Neither is certain UI features. Perhaps there's even more to it though, I'm not very experienced with iOS development and I'm literally in the stage of planning out how I'm gonna do this. Anyway, for just Metal support, would Metal-cpp simply be a better option (easy to use C and C++ together)? Would that outperform a Swift implementation (last I checked Swift can match C++ in few cases, but may have issues with certain algorithms due to lack of vectorization and other optimization. Things like this change all the time though.)?

So in summary, what is the best way to at least call Swift functions from C? That's the most important thing. I've heard of name mangling (using @_cdecl, which I've, again, heard is neither official or reliable) and overriding function pointers from a C struct.

1 Like

Hello. One way is using of *-Bridging-Header.h file. It is used for importing Swift code to Objective-C. In Objective-C world you can write in pure C, they are compatible and can be mixed together. The main limitation is that not all swift Types can be represented in Objective-C:

  • enum with associated value can't
  • only classes inherited from NSObject can be imported
  • structs can not be represented at all

Array in Swift is a struct. So, if you need a plain C array of integers, you need firstly convert it to Obj-C NSArray, and then in Obj-C world convert it to C array. This operation will have performance costs.

Metal is actually an Objective-C framework, not a Swift one (though Metal does work in Swift because Swift has Objective-C interoperation capabilities). Objective-C is a superset of C and interoperates nicely with plain C code. It does have a weird syntax though. If you want to learn Objective-C, here's a guide from Apple.

Otherwise, you're best off using Metal-cpp.

They'd probably have similar performance. Metal uses Objective-C objects (even Metal-cpp!), and Objective-C objects generally make optimizations (including vectorization) hard to implement.

In my experience the overhead of converting structures back and forth between swift and C/C++ plus the associated complexity overhead leads to an overall unsatisfactory solution.

You can do a quick experiment to check this.