Game World!

Join A World Of Gamers

Enter your email address:

Delivered by FeedBurner

Followers

Popular Posts

Friday, 2 July 2021

Can you write C++ in Swift?

 Is there a C++ library you’d like to consume in your iOS application? C++ is a low level programming language that has been around for over 35 years now.

Whilst C++ is a very old and complicated language and it is still very much relevant in todays world. C++ is predominantly used when higher performance is required. Examples of such libraries are Unreal Engine for gaming and OpenCV for live computer vision.

In fact Apple still employs C++ to write some of its most popular and performance requiring features. Rumour is that the Animoji feature is written in C++.

If you are building some C++ features in you Swift iOS app then consuming C++ from Swift is no straight forward task.

This post is about how to consume C++ code from Swift. I assume you know the basics of iOS development, Swift programming and Object Oriented Programming.

You don’t really need to know C++ programming. Just the basics of Object Oriented Programming. The C++ code that I will use in this post is very basic and easy to grasp. This is not a tutorial to show you how to program with C++.

In this tutorial I’ll first cover on a high level how consumption of C++ from Swift works. We’ll then create a SwiftUI app from scratch. We’ll then add some C++ that returns “Hello from CPP world!” message. Finally we’ll retrieve the “Hello from CPP world!” message and display it to the user.

I have used Swift 5.2.4 and Xcode 12.0 beta whilst writing this article.

How consuming C++ code from Swift work?

In essence Swift can’t consume C++ code directly. However Swift is capable of consuming Objective-C code and Objective-C (more specifically its variant Objective-C++) code is able to consume C++. Hence in order for Swift code to consume C++ code we must create an Objective-C wrapper or bridging code.

Designed by Ana Movileanu

Getting Started

In this section we will:

  1. Create a iOS SwiftUI app from scratch
  2. Add C++ code
  3. Create C++ Bridging code
  4. Consume C++ code from Swift

1. Create a iOS SwiftUI app from scratch

Let’s begin by creating a new SwiftUI app for iOS. Open Xcode and then from menu select File > New > Project…

Create a new project

Next from iOS template select App. Click Next.

use the iOS app template

Then on “Choose options for your new project” prompt call the app SwiftCPP. Make sure the “Interface:” option is SwiftUI, “Life Cycle:” is SwiftUI App and finally the “Language:” is set to Swift. All checkboxes can be left unchecked. Click Next.

new project options window

Then navigate to a folder where you’d like to store your project. Finally click Create.

2. Add C++ code

Next let’s ad some C++ code. From menu select File > New > File… When prompted “Choose a template for your new file” search and select C++ File under the iOS tab. Then click Next.

Next name the file HelloWorld and check “Also create a header file”. Click Next.

Finally click Create.

When prompted “Would you like to configure an Objective-C bridging header?” click Create Bridging Header.

The bridging header is where we’ll specify Xcode which Objective-C code we want to be consumed from Swift later in this tutorial.

Next let’s add some C++ code to our HelloWorld files. First let’s open the header file; HelloWorld.hpp. In simple terms the header file is like the protocol or interface.

Add the following code under #include <stdio.h> :

#include <string>class HelloWorld {
public:
std::string sayHello();
};

Next let’s add the implementation of the HelloWorld interface. Open HelloWorld.cpp and under #include "HelloWorld.hpp" add the following code:

std::string HelloWorld::sayHello() {
return "Hello from CPP world!";
}

3. Create C++ Bridging code

As mentioned earlier in the “How consuming C++ code from Swift works?” section, we aren’t able to consume C++ code from Swift directly. Rather Swift can consume Objective-C and Objective-C can consume C++.

Thus in section we’ll create a wrapper or bridging code between Swift and C++ in Objective-C.

Let’s add a new file. From menu select File > New > File… Next search and select Header File from the iOS tab. Click Next.

Name the file HelloWorldWrapper then click Create. Replace the file content to the following:

#import <Foundation/Foundation.h>@interface HelloWorldWrapper : NSObject- (NSString *) sayHello;@end

Next let’s create the implementation file of the HelloWorldWrapper interface. From menu select File > New > File… Then search and select Objective-C File from the iOS tab. Click Next.

Next name the file HelloWorldWrapper and click Next. Finally click Create.

Next change the file name from HelloWorldWrapper.m to HelloWorldWrapper.mm. Yes that is 2 m’s, it’s not a typo. The second “m” signals Xcode and the compiler that this Objective-C file will use C++ code.

Add an “m” to the extension of the file name

Next under #import <Foundation/Foundation.h> statement add the following code:

#import "HelloWorldWrapper.h"
#import "HelloWorld.hpp"
@implementation HelloWorldWrapper- (NSString *) sayHello {
HelloWorld helloWorld;
std::string helloWorldMessage = helloWorld.sayHello();
return [NSString
stringWithCString:helloWorldMessage.c_str()
encoding:NSUTF8StringEncoding];
}
@end

Above we are simply calling the C++ code and converting a C++ string to an Objective-C NSString.

4. Consume C++ code from Swift

Now that we have our C++ code wrapped in Objective-C, the Objective-C wrapper is not quite ready to be consumed. First we have to tell Xcode that we wish to consume the Objective-C code in Swift.

To do this we must the auto created SwiftCPP-Bridging-Header.h and add the following line:

#import "HelloWorldWrapper.h"

This tell Xcode to automatically create a Swift binding interface for the HelloWorldWrapper Objective-C code.

Now we are ready to consume the Objective-C code. Open ContentView.swift and the following code:

struct ContentView: View {
var body: some View {
Text("Hello, world!").padding()
}
}

to:

struct ContentView: View {
var body: some View {
Text(HelloWorldWrapper().sayHello()).padding()
}
}

The difference here is that instead of displaying "Hello, world!" we are now retrieving the message from the Objective-C HelloWorld wrapper by calling HelloWorldWrapper().sayHello().

Thats it! Run the app on a simulator and see it working. We are consuming C++ code from Swift! 🎉

Summary

In this post we learnt:

  • How to consume C++ from Swift

Final Notes

You can find the full source code below:

In the past I have been using OpenCV quite a lot, for which I need to consume C++ code from Swift. Whilst iOS can take machine learning models or use already created models through CoreML and Vision framework I still prefer to do some low level computer vision algorithms using OpenCV in some specific scenarios. That is because already off the shelf libraries and models do not always live up to the performance requirements.

Here are is an example of using OpenCV in iOS:

Floating Button

Button