3

I want to create an app for both iOS and Android native (I have used Xamarin in the past and I don't want to use it anymore), so my next choice was to write shared code in C++, which can be compiled on both platforms natively.

Now I want to know if I can use C++ directly from Swift. The only solutions I've found suggest creating a wrapper in Objective-C++ and exposing that through a bridging header, but I don't want this overhead.

Is this planned for Swift? Or are there other solutions to skip the Objective-C++ step?

vrwim
  • 13,020
  • 13
  • 63
  • 118
  • Related http://stackoverflow.com/questions/24042774/can-i-mix-swift-with-c-like-the-objective-c-mm-files – Ahmad F Apr 04 '17 at 14:04
  • Possible duplicate of [Can I mix Swift with C++? Like the Objective - C .mm files](http://stackoverflow.com/questions/24042774/can-i-mix-swift-with-c-like-the-objective-c-mm-files) – Kristopher Johnson Apr 04 '17 at 14:28

3 Answers3

3

That's not currently supported. There are only two approaches for talking to C++ code from Swift code:

  1. Wrap your C++ code in ObjC using Objective-C++, as you already found.

  2. Take advantage of the fact that C++ is mostly compatible with C, and Swift can call C, and write a C wrapper around your C++ classes, and use that from Swift. A common approach would be:

cppwrapper.h

struct MyCppClass; // In C++ class and struct are the same, so this looks like a C struct to C, and as long as you don't look inside it, you can use pointers to it in C code.

extern "C" { // Tell C++ to turn off overloading based on type so it's C-compatible.

struct MyCppClass* MyCppClass_new( int firstParam );
void MyCppClass_delete( struct MyCppClass* inThis );
void MyCppClass_setFirstParam( struct MyCppClass* inThis, int firstParam );

} // extern "C"

cppwrapper.cpp

#include "cppwrapper.h"
#include "MyCppClass.hpp"    

extern "C" MyCppClass* MyCppClass_new( int firstParam )
{
    return new MyCppClass( firstParam );
}

extern "C" void MyCppClass_delete( MyCppClass* inThis )
{
    delete inThis;
}

extern "C" void MyCppClass_setFirstParam( struct MyCppClass* inThis, int firstParam )
{
    inThis->SetFirstParam( firstParam );
}

You could then even define a MyCppClassSwiftWrapper that has an instance variable of type COpaquePointer in which you store the C++ object. This class would call MyCppClass_new in its constructor, MyCppClass_delete in its destructor, and would contain a wrapper around MyCppClass_setFirstParam that uses the COpaquePointer as the inThis parameter into it.

I once wrote a (very primitive) utility that lets you mark up C++ headers and generate simple C and Swift wrappers for them automatically (https://github.com/uliwitness/cpptoswift/) but it won't work with templates and you'll probably have to add more type mappings to it. It also doesn't yet handle passing/returning C++ objects correctly yet.

There's also https://github.com/sandym/swiftpp/ which does all that better, but I think it still uses Objective-C under the hood for its wrapper, but at least you don't have to write it yourself.

uliwitness
  • 8,532
  • 36
  • 58
0

I've created an Objective-C++ framework, that helps to simplify this kind of bridging: CXXProxyKit. Please take a look!

khrykin
  • 153
  • 1
  • 6
-1

If you include your C++ headers as C compatible in the Bridging-Header.h you can use it seamlessly in your swift project.

#ifndef Bridging_Header_h
#define Bridging_Header_h

#import <Foundation/Foundation.h>
#include "CPlusPlusHeader.h"


#endif /* Bridging_Header_h */
zero3nna
  • 2,770
  • 30
  • 28
  • What's the catch? I didn't know this was possible. – vrwim Apr 04 '17 at 14:11
  • The key is to make an Objective-C bridging header that #includes C-compatible C++ headers that are marked as C compatible with the `extern "C" {}` trick. – zero3nna Apr 04 '17 at 14:23
  • 3
    Note that this only lets you call `extern "C"` functions and use C-compatible types. You can't directly use C++ classes or other non-C-compatible features of C++. – Kristopher Johnson Apr 04 '17 at 14:27