Using C++ Dynamic/Static Libraries in Swift

Hi,

I have some core functioanlity which is written in C++. I would like to use this in my Swift application as a dynamic library or a static library. Can someome please guide how to achieve the same ?

Swift cannot call C++ code directly [1]. The standard workaround is to wrap the functionality you need in a language that Swift can call directly (C, Objective-C, Objective-C++).

I would like to use this in my Swift application as a dynamic library or a static library.

While Swift can’t call C++ directly, Xcode is happy to work with it. My preferred option here is not to use a library but instead add your C++ source code to your Xcode project and build it (and your wrapper) all in one go. This radically simplifies the integration process.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

[1] Although there is work afoot to make that happen. See [Manifesto] Interoperability between Swift and C++ on the Swift Forums.

Hi,

Thank you for your prompt response. Because the project is huge and has too many dependencies, it would not be possible to bring the entire project in xcode. Hence, i plan to compile the project into a .dylib or a .a file and then used it in xcode via swift or objective c. I agree that a bridge would anyway be needed which is fine. Currently, would like to udnerstand what should the approach be and how it can be achieved.

From the perspective of your Swift client, the easiest approach here would be for your external build system to create a framework. The framework’s headers would contain the C (or Objective-C) headers for your bridge. The framework’s dynamic library would contain your C++ code and the implementation of your bridge. At this point your Swift client can use the framework like it would any system framework (indeed, there are various system frameworks that rely on a C++ core wrapped in exactly this fashion).

If you’re only targeting macOS, you can do exactly this. If your targets include one or more iOS-based platforms, you need to do this step multiple times, once for each platform, and then merge the resulting frameworks into an XCFramework. See WWDC 2019 Session 416 Binary Frameworks in Swift (despite the session’s title, the XCFramework parts of this talk also apply to non-Swift frameworks).

IMPORTANT For iOS-based platforms, each OS and its simulator are different platforms.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Thanks for the reply!

Can you point me to any article ot tutorial for this ?

Can you point me to any article ot tutorial for this ?

No, sorry. I’m sure that such tutorials exist, but it’s not something I’d have cause to look up.

IMO the best way to get started here is to use Xcode to create a project that builds a test framework, combining a test C++ class with a test Objective-C wrapper. Get that working, then look at the build transcript to see how Xcode does all of its magic.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Just to clarify something here. Swift cannot use C++ code directly. It doesn't matter if it is in a dylib or a static archive. The code and the headers are C++. That won't work with Swift. The only thing Swift will accept is a plain C wrapper or Objective-C. You can get clever and write an Objective-C++ wrapper. That will work too as long as you make sure that no C++ ever bleeds into the public headers.


A have a forum post that describes how to do this. It isn't a true tutorial. Here is a link to a more real-world example: gist.github.com/etresoft/076679ecef38521b5283554dca62e70f (the link is incomplete to avoid automatic moderation). This is just a demonstration to show how to use private Objective-C headers to keep the C++ out of the public headers. The rest of it is a long story that I don't want to tell and you don't want to hear.


Finally, I should point out that it is possible to hand-roll a framework without Xcode. If you have an established project outside of Xcode, this is the easiest way to do it. Just review existing frameworks and maybe even build a demo framework using Xcode templates. That will show you what the structure of the framework must look like. It will also give you a plist file that you can stuff in.


Probably the biggest difficulty is dealing with other dynamic libraries inside your framework. Everything has to be signed and properly referenced. You may need to hack up the framework's linkage using "install_name_tool". This is where you want to review how existing apps with embedded frameworks look. You can use "otool -L" to inspect the dynamic linkage. Depending on the project, this could be tricky.

Fair ! Thanks a lot ! Will try this out and get back in case of any queries.

Thanks John !

Lets say I use a static library i.e. I have a small C++ project that I compile into a .a file. Now I would like to use this .a file in my Objective C framework. Are you aware of how this can be achieved?

Thanks in advance.

That's not really any different. C is also incompatible with C++. If you want to use C++ with C, you have to wrap it in C. C++ does include special wrapping macros that can expose C++ functions as C functions with C linkage. These functions can then be used directly from C.


But otherwise, it is the same. You still can't let any true C++ structures like classes or templates be visible to C. Some projects have tried to add C wrappers to their C++ code, with varying success. Usually they just thunk the C++ object pointers into some kind of void * and cast it back inside the library. Avoiding that kind of thing is one of the foundational concepts of Swift.


Ironically enough, Swift is written in C++.

Using C++ Dynamic/Static Libraries in Swift
 
 
Q