1

I’d like to write some native code in either C or C++ to be used with Swift on iOS. This code would mainly be invoked from Swift but would also need to callback to Swift as well.

What is the mechanism for interfacing Swift with each of these 2 languages?

Which of C or C++ would have the least constraints in this kind of interface and why? Are there any performance difference in the cross-language calls?

Christophe
  • 68,716
  • 7
  • 72
  • 138
Clancy Merrick
  • 855
  • 1
  • 8
  • 16
  • I guess the land question is the ABI you are expected to use. Are there any constraints? is that supposed to be portable code? – OznOg Apr 28 '19 at 12:23
  • The C or C++ code would desirably be portable to other platforms but the interfacing code clearly not. – Clancy Merrick Apr 28 '19 at 12:27
  • not really clear what you are trying to achieve, the C/C++ would be third party libs or your own code? would you deliver binaries and/or sources? – OznOg Apr 28 '19 at 12:31
  • The native code would be my own and I only want to interface with the binaries. – Clancy Merrick Apr 28 '19 at 12:39
  • This question got a lot of downvotes and close votes due to an unfortunate wording ("best", "easiest") that may appear subjective. However, this question is well founded and can be answered with objective arguments. So I slightly reformulated in order to avoid the subjective impression – Christophe Apr 28 '19 at 13:05
  • @Christophe: I am not sure that wording was the only problem. In any case, the OP has asked [a similar question here](https://stackoverflow.com/questions/55894165/how-to-interface-java-or-kotlin-on-android-with-c-or-c) and it was closed and DVed in the same fashion. Thus, that may illustrate that we have to be careful how we endorse what is on/off topic, since new users can get their account q-banned based on the wrong advice. – halfer Apr 28 '19 at 21:33
  • Would you be minded to try reopening this question? I would wonder if there would be an existing duplicate, but it is not a tag I am active in. – halfer Apr 28 '19 at 21:35
  • 2
    @halfer ok, I'll vote for reopening it. Going through the 18 questions that have the three language tags, I didn't find a clear dupe that answered would on its own answer this question. – Christophe Apr 28 '19 at 22:04
  • Thanks @Christophe. I am happy to follow your lead, I will reopen too. – halfer Apr 28 '19 at 22:05
  • I’m sorry for the apparently poor wording of my question. I wasn’t expecting such a reaction but will try to learn from this and word my questions more appropriately. – Clancy Merrick Apr 29 '19 at 22:08
  • 1
    No worries @Clancy. Most new users don't know to avoid asking subjective questions, and getting folks to read the manual is an enormously hard challenge for any community `:-)`. – halfer Apr 30 '19 at 07:53
  • Although this question reopened for a time, some folks seem to have closed it again. They were evidently determined to do so, but such disagreements do happen here from time to time. cc @Christophe. – halfer Apr 30 '19 at 07:55
  • @halfer yes. And this is sad: this kind of question is extremely useful for anybody trying to integrate portable cross-platform components in the iOS and macOS environment. similar questions on other programming languages helped me to save a lot of time to start experimenting with interoperability. – Christophe Apr 30 '19 at 08:07
  • 2
    Urgh, 11 downvotes is just highly excessive. I'm all in favour of DVing things in general, but honestly, this might encourage the Q author to delete the post. That would lose @Christophe's valuable contributions below. I am generally not in favour of voting to cancel out other folks' votes, but I will make an exception today. – halfer Apr 30 '19 at 08:55
  • (I am not permitted to reopen the question again). – halfer Apr 30 '19 at 08:57
  • I feel discouraged from using this forum. So much control and censorship. I just wanted some basic advice and got hit with a barrage of haters. – Clancy Merrick Apr 30 '19 at 10:09
  • @ClancyMerrick yes, I fully understand. I cannot agree with these practices either. I nevertheless hope that my answer helped :-) – Christophe Apr 30 '19 at 12:16
  • Yes, thank you - your answer really did help. Is there a way to flag it is the “accepted” answer? – Clancy Merrick May 01 '19 at 08:36

2 Answers2

14

The interoperability of swift with C or C++ goes over Objective-C, via the bridging header.

In this Objective-C header, you may include C headers, since Objective-C is interoperable with C. Swift can then not only work with the C functions, but also with C structures and unions.

You may also use interoperability with C++ using Objective-C++. Wowever, neither Objective-C nor Swift can work with C++ classes and their semantic. So you'll face the same issues than when trying to work with C++ from C. In this and this answers, you'll find more infos about C++ interoperability.

So what's easier to call from/to Swift? Definitively C


Small step by step demo:

1) Create a Swift project in XCode
2) Add a c file test.c
3) When you've added the c file, XCode will ask you if a briging header is to be created: just confirm.
4) Use the following code

In the bridging header (or in a header included in the bridging header):

// C functions
int myCFunction(int a);
void myCFunctionWithCallback(int a, int (*f)(int));

// Swift functions accessible from C
extern int mySwiftFunction(int x);

Example test.c file:

#include <stdio.h>

// simple example with a hardcoded swift callback
int myCFunction(int a)
{
    printf ("myCFunction in C called with %d\n", a);
    printf ("Now calling Swift from C :\n");
    int z = mySwiftFunction(10);
    printf ("Result returned in C:%d\n", z);
    return 2*a;
}

// example with a function pointer to a swift callback
void myCFunctionWithCallback(int a, int (*f)(int))
{
    printf ("myCFunctionWithCallback in C called with %d\n", a);
    printf ("Now calling Swift from C :\n");
    int z = f(a);
    printf ("Result returned in C:%d\n", z);
}

Example main.swift file:

import Foundation

@_silgen_name("mySwiftFunction")  // vital for the function being visible from C
func mySwiftFunction(x: Int) -> Int
{
    print ("mySwiftFUnction called in Swift with \(x)")
    return 3*x
}

func mySwiftCallback(x: Int32) -> Int32
{
    print ("mySwiftCallback called in Swift with \(x)")
    return 7*x
}

print("Starting Swift/C interoperability demo !")
let a = myCFunction(12);
print ("returned result in Swift is \(a)")

print ("Now test with a callback function pointer:")
myCFunctionWithCallback(13, mySwiftCallback )

The trick @_silgen_name for making swift functions visible in C is explained in this other SO answer and is documented here

Christophe
  • 68,716
  • 7
  • 72
  • 138
-2

You can Use Bridging header file to map the code written in Objective-C to use in Swift. You cannot use C/C++ code because Xcode itself only supports Objective-C and Swift. In Bridging header file you have to import the header path of Objective-C File which you have to import in Swift project.