How does a Swift function differ from a C one?

I either read this thread or one similar to it. It mentions that you can annotate functions that work like the ones in C with the "@convention(c)" attribute. I'm assuming that C functions have (nearly) no context besides their parameter types and return types. What richness do Swift functions have (by default) that prevent them from being automatically compatible with C function pointers?

(I'm wondering so a type idea I have could hook into that context someday.)

In this thread about function equality in Swift @Joe_Groff said ("[]" inserted for clarification):

However C function pointers, IIRC, are just raw pointers to the function code.

There are a couple of distinct axes here that I can think of:

  1. Context: does the function carry a context (via pointer or otherwise).
  2. Calling convention: how are arguments passed and return values received (i.e. which registers/positions on the stack are used).

If you consider this as a table:

Calling Convention Has Context No Context
C N/A @convention(c)
Swift @convention(swift) @convention(thin)

(@convention(block) is kinda' complicated, methinks. You probably want to read the Clang docs on blocks to understand it, in case you're interested.)

A function is said to have "a thin calling convention" if it doesn't carry around a context (I think this is compiler-internal terminology and not user facing). This means that both @convention(c) functions and @convention(thin) functions have "a thin calling convention".


It mentions that you can annotate functions that work like the ones in C with the " @convention(c) " attribute.

Yes, but you probably don't want to do this unless you're doing FFI (directly or via some other library).

I'm assuming that C functions have (nearly) no context besides their parameter types and return types.

Yes, but I feel that the terminology in this sentence conflates two (related) things. C function types are entirely described by their parameter types and return types. An @convention(c) function (value) does not carry a context.

What richness do Swift functions have (by default) that prevent them from being automatically compatible with C function pointers?

There's two different things -- the calling convention and the context. There's a recent blog post which has some interesting tidbits about the register usage in Swift's native calling convention.

(I'm wondering so a type idea I have could hook into that context someday.)

That sounds at least a little bit risky -- I'm not entirely sure of all the guarantees that are made, what potential things you might assume, and how they could break if you do unsafe shenanigans with the context. Probably best if more experienced people can chime in with opinions here.

Thin conventions like @convention(c) are just function pointers; they cannot carry a context and so cannot preserve whatever dynamic type information you'd like to be able to recover. It would probably also be difficult to guarantee its preservation in @convention(block) functions. But none of that should be a problem (except perhaps the use of blocks in bridging to Objective-C); it's just a limit of what you can guarantee, but that will inevitably be limited since, of course, someone could always wrap your function value.