# Best way to call a Swift function from C?

**URL:** <https://forums.swift.org/t/best-way-to-call-a-swift-function-from-c/9829>\
**Category:** Using Swift\
**Tags:** ffi\
**Created:** [February 12, 2018, 5:15pm UTC](https://forums.swift.org/t/best-way-to-call-a-swift-function-from-c/9829 "2018-02-12T17:15:22Z")\
**Posts on this page:** 19\
**Page:** 1

<div class="post-metadata">

**Author:** ![Max\_Desiatov](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/max_desiatov/32/20654_2.png) [@Max\_Desiatov](https://forums.swift.org/u/Max_Desiatov)\
**Post date:** [February 12, 2018, 5:15pm UTC](https://forums.swift.org/t/best-way-to-call-a-swift-function-from-c/9829/1 "2018-02-12T17:15:22Z")

</div>

Hi all,

What would you recommend is the best way to call a Swift function from C? This would also allow Swift functions to be called from other languages that support C FFI.

My understanding is that currently the only way is to call a mangled function name directly, but maybe there is a similar thing to

```
#[no_mangle]
pub extern "C" fn double(x: i32) -> i32 {
    x * 2
}

```

in Rust or `extern "C"` in C++ that turns off mangling?

---

<div class="post-metadata">

**Author:** ![Joe\_Groff](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/joe_groff/32/1929_2.png) [@Joe\_Groff](https://forums.swift.org/u/Joe_Groff)\
**Post date:** [February 12, 2018, 5:41pm UTC](https://forums.swift.org/t/best-way-to-call-a-swift-function-from-c/9829/2 "2018-02-12T17:41:22Z")

</div>

There's no official way yet. Aside from name mangling, Swift functions use a different calling convention from C. Unofficially, if you're willing to deal with more than the usual amount of code breakage and compiler bugs, there's an unofficial attribute `@_cdecl` that does this:

```swift
@_cdecl("mymodule_foo")
func foo(x: Int) -> Int {
  return x * 2
}

```

which you can then call from C:

```swift
#include <stdint.h>

intptr_t mymodule_foo(intptr_t);

intptr_t invoke_foo(intptr_t x) {
  return mymodule_foo(x);
}

```

---

<div class="post-metadata">

**Author:** ![eskimo](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/eskimo/32/13558_2.png) [@eskimo](https://forums.swift.org/u/eskimo)\
**Post date:** [February 13, 2018, 9:48am UTC](https://forums.swift.org/t/best-way-to-call-a-swift-function-from-c/9829/3 "2018-02-13T09:48:38Z")

</div>

While there’s no official way to call a Swift function directly from C, you can set up a function pointer that’s callable from C. Whether that helps you depends on your exact circumstances. For example, on Apple platforms it’s super useful for integrating with C APIs that use C callbacks (things like `CFRunLoop` observers).

Pasted in a below is an example sans anything Apple-ish.

Share and Enjoy  
—  
Quinn “The Eskimo!”  
Apple Developer Relations, Developer Technical Support, Core OS/Hardware  
`let myEmail = "eskimo" + "1" + "@apple.com"`

```
// main.swift

private func printGreeting(modifier: UnsafePointer<CChar>) {
    print("Hello \(String(cString: modifier))World!")
}

var callbacks = SomeCLibCallbacks(
    printGreeting: { (modifier) in
        printGreeting(modifier: modifier)
    }
)
SomeCLibSetup(&callbacks)

SomeCLibTest()

// SomeCLib.h

#ifndef SomeCLib_h
#define SomeCLib_h

struct SomeCLibCallbacks {
    void (* _Nonnull printGreeting)(const char * _Nonnull modifier);
};
typedef struct SomeCLibCallbacks SomeCLibCallbacks;

extern void SomeCLibSetup(const SomeCLibCallbacks * _Nonnull callbacks);

extern void SomeCLibTest(void);

#endif

// SomeCLib.c

#include "SomeCLib.h"

static SomeCLibCallbacks sCallbacks;

extern void SomeCLibSetup(const SomeCLibCallbacks * callbacks) {
    sCallbacks = *callbacks;
}

extern void SomeCLibTest(void) {
    sCallbacks.printGreeting("Cruel ");
}

```

---

<div class="post-metadata">

**Author:** ![pvieito](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/pvieito/32/33613_2.png) [@pvieito](https://forums.swift.org/u/pvieito)\
**Post date:** [August 26, 2018, 9:36pm UTC](https://forums.swift.org/t/best-way-to-call-a-swift-function-from-c/9829/5 "2018-08-26T21:36:20Z")

</div>

Is there any intention to convert `@_cdecl` into a public attribute? I think its use is extended and useful enough to convert it to something similar to `@objc`:

```swift
// Exposed to C ABI as `void printInfo()`
@c func printInfo() { … }

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

// Exposed to C ABI as `char * getInfo(char * input, int32_t count)`
@c func getInfo(from input: String, count: Int32) -> String { … }

```

---

<div class="post-metadata">

**Author:** ![jrose](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jrose/32/408_2.png) [@jrose](https://forums.swift.org/u/jrose)\
**Post date:** [August 27, 2018, 4:14pm UTC](https://forums.swift.org/t/best-way-to-call-a-swift-function-from-c/9829/6 "2018-08-27T16:14:23Z")

</div>

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:

> ```swift
> // 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.

```swift
@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.

---

<div class="post-metadata">

**Author:** ![QuinceyMorris](https://avatars.discourse-cdn.com/v4/letter/q/d26b3c/32.png) [@QuinceyMorris](https://forums.swift.org/u/QuinceyMorris)\
**Post date:** [August 27, 2018, 5:08pm UTC](https://forums.swift.org/t/best-way-to-call-a-swift-function-from-c/9829/7 "2018-08-27T17:08:02Z")

</div>

Where does `convention(c)` fit into this?

---

<div class="post-metadata">

**Author:** ![Ponyboy47](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/ponyboy47/32/2605_2.png) [@Ponyboy47](https://forums.swift.org/u/Ponyboy47)\
**Post date:** [August 27, 2018, 5:23pm UTC](https://forums.swift.org/t/best-way-to-call-a-swift-function-from-c/9829/8 "2018-08-27T17:23:01Z")

</div>

That is used for calling C code from swift, like when a swift closure is really just a wrapper around a C function.

For example, when using `glob(3)` with the `GLOB_ALTDIRFUNC` flag, you could set the `pglob->gl_stat` variable using the following type:

```swift
public var stat: (@convention(c) (UnsafePointer<CChar>?, UnsafeMutablePointer<stat>?) -> Int32)

```

The `gl_stat` variable is a function with the C signature: `int stat(const char * pathname, struct stat *buf)`

---

<div class="post-metadata">

**Author:** ![Joe\_Groff](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/joe_groff/32/1929_2.png) [@Joe\_Groff](https://forums.swift.org/u/Joe_Groff)\
**Post date:** [August 27, 2018, 5:23pm UTC](https://forums.swift.org/t/best-way-to-call-a-swift-function-from-c/9829/9 "2018-08-27T17:23:50Z")

</div>

`@convention` is orthogonal, since it affects the type of function values. In Swift we change conventions automatically when references to functions or methods are taken as closure values. The `@objc` attribute, and this proposed `@c` attribute, affect how a declaration is exported at the ABI level.

---

<div class="post-metadata">

**Author:** ![pvieito](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/pvieito/32/33613_2.png) [@pvieito](https://forums.swift.org/u/pvieito)\
**Post date:** [August 27, 2018, 11:04pm UTC](https://forums.swift.org/t/best-way-to-call-a-swift-function-from-c/9829/10 "2018-08-27T23:04:19Z")

</div>

> [@jrose](#):
>
> 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 *` .

Yeah, in my example the idea was that `input` should be a null-terminated `char *` so under-the-hood the C-to-Swift interop would use something as `String.init(cString:)` to convert it, being `count` a random independent parameter.

If you want to use the length you could always do it manually:

```swift
// Exposed to C ABI as `void printInfo(char * input, int inputLenght)`
@c func printInfo(from input: UnsafePointer<CChar>, inputLenght: Int) { … }

```

Also I think that `@c` (or whatever is named) should bridge to pure-C types (no `id`, `char *` instead `NSString`) so using both attributes on a function would generate two different entry points.

In a way, the `@c` naming could blend beautifully in a future with more language-interop attributes available 🙂:

- `@c`
- `@cpp`
- `@objc`
- `@csharp`

Or maybe should we go with a new `@interop` attribute?

```swift
// Exposed to C ABI as `void printInfoWithInput(char * input)`
// Exposed to Objective-C ABI as `void printInfo(NSString * input)`
@interop(c, name: printInfoWithInput) @interop(objc) 
func printInfo(from input: String) { … }

```

---

<div class="post-metadata">

**Author:** ![Krischu](https://avatars.discourse-cdn.com/v4/letter/k/ed8c4c/32.png) [@Krischu](https://forums.swift.org/u/Krischu)\
**Post date:** [January 12, 2019, 8:11am UTC](https://forums.swift.org/t/best-way-to-call-a-swift-function-from-c/9829/11 "2019-01-12T08:11:11Z")

</div>

> [@Joe\_Groff](#):
>
> ```
> @_cdecl("mymodule_foo")
> func foo(x: Int) -> Int {
> return x * 2
> }
> 
> ```

I'm facing the same problem. Trying your suggestion gives an error from Xcode (10.1):

@\_cdecl can only be applied to global functions

As I understand the above thread served as a discussion of implementation this mechanism into the Swift language, right?

Or is there a finalized method yet to do this? I'm getting compilation errors on all implementation examples I tried yet.

---

<div class="post-metadata">

**Author:** ![Krischu](https://avatars.discourse-cdn.com/v4/letter/k/ed8c4c/32.png) [@Krischu](https://forums.swift.org/u/Krischu)\
**Post date:** [January 16, 2019, 8:03am UTC](https://forums.swift.org/t/best-way-to-call-a-swift-function-from-c/9829/13 "2019-01-16T08:03:52Z")

</div>

Thanks for the pointer. A bit lengthy that talk but interesting nonetheless. Regarding the topic: I still don't have a working example. OTOH I'm rethinking my program architecture whether I really need calling a Swift function from C 🙂

But interest for the formal solution of the above is still there.  
What I find weird so to say with Swift, that it is a chimera these days. Examples you find can be a year old and no longer work. And you gotta collect your knowledge tediously. Would I buy a book on Swift 4 in February it will surely be outdated.

--  
Christoph

---

<div class="post-metadata">

**Author:** ![Krischu](https://avatars.discourse-cdn.com/v4/letter/k/ed8c4c/32.png) [@Krischu](https://forums.swift.org/u/Krischu)\
**Post date:** [January 16, 2019, 12:44pm UTC](https://forums.swift.org/t/best-way-to-call-a-swift-function-from-c/9829/14 "2019-01-16T12:44:17Z")

</div>

I found a blatantly simple solution [here](http://www.perry.cz/clanky/swift.html)

---

<div class="post-metadata">

**Author:** ![ingconti](https://avatars.discourse-cdn.com/v4/letter/i/50afbb/32.png) [@ingconti](https://forums.swift.org/u/ingconti)\
**Post date:** [January 20, 2020, 11:55am UTC](https://forums.swift.org/t/best-way-to-call-a-swift-function-from-c/9829/15 "2020-01-20T11:55:56Z")

</div>

my 2 cents for whom want a working minimal sample.

> **[GitHub - ingconti/CallingSwiftFromC: CallingSwiftFromC from time ideas on...](https://github.com/ingconti/CallingSwiftFromC)**
>
> CallingSwiftFromC from time ideas on https://forums.swift.org/t/best-way-to-call-a-swift-function-from-c/9829 - GitHub - ingconti/CallingSwiftFromC: CallingSwiftFromC from time ideas on https://for...

---

<div class="post-metadata">

**Author:** ![Geordie\_J](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/geordie_j/32/839_2.png) [@Geordie\_J](https://forums.swift.org/u/Geordie_J)\
**Post date:** [March 26, 2020, 12:33pm UTC](https://forums.swift.org/t/best-way-to-call-a-swift-function-from-c/9829/16 "2020-03-26T12:33:09Z")

</div>

Hi @Joe_Groff @jrose I'm pinging you here because you seem well versed with the ins and outs of calling Swift from C.

We were relying on `@_cdecl` to call Swift code from Python, we also use it to call Swift code from the JNI on Android. Yesterday we updated to Swift 5.2 and it seems our `@_cdecl public func xyz` Swift functions have disappeared from the symbol table and can no longer be called.

Is there still an unofficial or official way of calling Swift from C? The workaround @eskimo mentioned (which is very clever, by the way, thanks for the insight!) might prove difficult to implement for our use cases.

---

<div class="post-metadata">

**Author:** ![Joe\_Groff](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/joe_groff/32/1929_2.png) [@Joe\_Groff](https://forums.swift.org/u/Joe_Groff)\
**Post date:** [March 26, 2020, 4:28pm UTC](https://forums.swift.org/t/best-way-to-call-a-swift-function-from-c/9829/17 "2020-03-26T16:28:17Z")

</div>

The C entry point for a public function should also be public. Have you filed a bug?

---

<div class="post-metadata">

**Author:** ![Geordie\_J](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/geordie_j/32/839_2.png) [@Geordie\_J](https://forums.swift.org/u/Geordie_J)\
**Post date:** [March 26, 2020, 4:30pm UTC](https://forums.swift.org/t/best-way-to-call-a-swift-function-from-c/9829/18 "2020-03-26T16:30:07Z")

</div>

Not yet. Wasn't sure whether this was a bug given it's "underscored" behaviour- thought maybe there's a new way (but couldn't see it in release notes). Should I file a bug on Jira or a radar somewhere on Apple?

---

<div class="post-metadata">

**Author:** ![Joe\_Groff](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/joe_groff/32/1929_2.png) [@Joe\_Groff](https://forums.swift.org/u/Joe_Groff)\
**Post date:** [March 26, 2020, 4:33pm UTC](https://forums.swift.org/t/best-way-to-call-a-swift-function-from-c/9829/19 "2020-03-26T16:33:21Z")

</div>

Either one is great. If you don't have any secrets in the bug report you can't share publicly, we would prefer Jira though.

---

<div class="post-metadata">

**Author:** ![leisurehound](https://avatars.discourse-cdn.com/v4/letter/l/50afbb/32.png) [@leisurehound](https://forums.swift.org/u/leisurehound)\
**Post date:** [August 21, 2021, 12:19am UTC](https://forums.swift.org/t/best-way-to-call-a-swift-function-from-c/9829/20 "2021-08-21T00:19:14Z")

</div>

> there’s an unofficial attribute `@_cdecl` that does this:

I'm noticing that the test target can't find mymodule\_foo when linking tests. Is there a workaround for that? Should I create a module map? I have a C module already for the file where I've placed your example (which swift calls into successfully), changing the "mymodule\_foo" to the same name as the module that its in doesn't seem to help. Thoughts?

---

<div class="post-metadata">

**Author:** ![llothar](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/llothar/32/19376_2.png) [@llothar](https://forums.swift.org/u/llothar)\
**Post date:** [August 26, 2021, 11:35pm UTC](https://forums.swift.org/t/best-way-to-call-a-swift-function-from-c/9829/21 "2021-08-26T23:35:04Z")

</div>

Is this problem now fixed? I consider moving my project from Objective-C++ to Swift.
