[Accepted] SE-0495: C-compatible functions and enums

Hey all,

The review of SE-0495: C-compatible functions and enums ended on October 9th (with a short extension to discuss a late modification).

Feedback on this proposal was generally positive. There were a few questions raised on the thread worth mentioning:

  • Q: If you have C size_t it comes in as Int for “system” headers via Clang, but Int would normally bridge to ptrdiff_t . What type do I need to use on the Swift side to implement a function that takes/returns a size_t in a C header?

    A: Whatever type the C function imports as (Int in this case).

  • Q: Is @c too terse/unspecific?

    A: We don't think so. It is short, but it mirrors @objc, and we think that it will not be an issue at actual use sites.

  • Q: How will we handle types that are not uniformly supported by compilers / C language versions?

    A: Generated headers are expected to be consumable by a reasonable baseline of common compilers. Types or functions that cannot be supported by a mainstream C language version or compiler would be suppressed in the generated header. The specifics of how this works are an implementation detail, and do not need to be hashed out in this proposal.

The Language Steering Group has decided to accept this proposal.

Thanks to everybody who participated in the review!

—Steve Canon, review manager

15 Likes

This is not correct. Swift can map size_t to Int on import because they have the same ABI, but the generated header goes beyond ABI into API, where signedness matters (not just for diagnostics, but also for promotion). Fortunately, the proposal does not claim this; it maps UInt to size_t and Int to ptrdiff_t.

2 Likes

What you’re are describing is correct for a @c function that isn’t implementing a function declared in a C header, but this question was about what happens for a marked implementation of a function with a C header prototype.

(I.e. it is the importer’s view of the type mapping that determines if an implementation matches a C header’s prototype.)

Thanks. I guess it’s ambiguous what fclout was asking about here:

If the Swift side uses @c @implementation, then the header uses size_t and the implementer uses Int. However, if the generated header is being used, and, say, the implementation of the size_t-consuming function calls an imported size_t-consuming function, the mismatch will still show up. There’s also a bit of weirdness here around Swift clients of the API, which may see a size_t in the generated header but UInt in the swiftinterface/swiftmodule, and be unable to pass an Int to it. I guess the recommendation is “if you care strictly about matching up with C stdlib types you should use @c @implementation”.