Best way to call a Swift function from C?

I think we do want to do this, but it needs a formal proposal and some more implementation work to check that the arguments are actually valid for C. For instance, you wrote this:

// Exposed to C ABI as `void printInfoWithInput(char * input, int count)`
@c(printInfoWithInput)
func printInfo(from input: String, count: Int) { … }

But there's no way to go from a char * to a String without taking the count into account (unless you want to guarantee that input is also null-terminated). This also isn't compatible with the behavior of @objc, which translates String to NSString *.

The other big question is whether arbitrary other Objective-C types or types bridgeable to Objective-C are allowed, since they aren't cross-platform.

@cdecl func getOpaqueThing() -> Any
// `id getOpaqueThing(void)`, or an error?

@cdecl func compute(input: Foundation.Data) -> Int
// `intptr_t computeWithInput(NSData *input)`, or an error?
// Also, 'intptr_t' or 'NSInteger'? 'long' unfortunately wouldn't work on Windows.

I imagine different people will have different opinions on this. One way out would be to allow both @objc and @cdecl to be present on a function, and for them to enforce different rules. (We'd probably also want to consider allowing @cdecl on enums in this case too, but then again standard C doesn't have enums with underlying types.)

I do think @c is a little too short to be a good attribute name, but I guess @cdecl no longer fits our naming convention.

6 Likes