Import headers from c++ library in swift

Viewed 76

I am learning how to communicate between swift and c++ for ios. As a first step I have looked on this example:

https://github.com/leetal/ios-cmake

There is an example-app that I have managed to compile and run. Took some time to get it to work. That is an objective-c project.

The next step is to create a new swift project and try and import the compiled library and use the headers in swift instead.

I have not managed to do that. I think the current problem is that I cannot include the header HelloWorldIOS.h.

import SwiftUI
import HelloWorldIOS.h <- No such module found

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

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

I have tried to create a bridging file example-Bridging-Header.h as suggested here: https://developer.apple.com/documentation/swift/importing-objective-c-into-swift

It looks like:

//
//  example-Bridging-Header.h
//  example-swift
//

#ifndef example_Bridging_Header_h
#define example_Bridging_Header_h

#import "HelloWorldIOS.h"

#endif /* example_Bridging_Header_h */

I have also added the path to the headers in Target - Build Settings - Header Search Paths

The Objective-C Bridging Header looks like example-swift/example-Bridging-Header.h.

Are there any good instructions for how to call c++ code from a compiled library? I hoped this example I found would be easy to get to work.

The comment below helped me plus that I had to link to libc++.tbd.

2 Answers

You don't import anything in your Swift code when Objective-C headers are imported in the bridging header. All public interfaces available from the imported files get available in the entire Swift module by default after that.


Sample listing

TDWObject.h

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface TDWObject : NSObject

- (void)someCPPCode;

@end

NS_ASSUME_NONNULL_END

TDWObject.mm

#include <iostream>

#import "TDWObject.h"

@implementation TDWObject

- (void)someCPPCode {
    std::cout << "Hello from CPP cout" << std::endl;
}

@end

Some-Bridging-Header.h

#import "TDWObject.h"

main.swift

TDWObject().someCPPCode()

Provided the main.swift file is the entry point of the program, it will print Hello from CPP cout.

You can use Scapix Language Bridge to automatically bridge C++ to Swift (among other languages). Bridge code automatically generated on the fly directly from C++ header files. Here is an example:

C++:

#include <scapix/bridge/object.h>

class contact : public scapix::bridge::object<contact>
{
public:
    std::string name();

    void send_message(const std::string& msg, std::shared_ptr<contact> from);
    void add_tags(const std::vector<std::string>& tags);
    void add_friends(std::vector<std::shared_ptr<contact>> friends);

    void notify(std::function<bool(std::shared_ptr<contact>)> callback);
};

Swift:

class ViewController: UIViewController {
    func send(friend: Contact) {
        let contact = Contact()

        contact.sendMessage("Hello", friend)
        contact.addTags(["a","b","c"])
        contact.addFriends([friend])

        contact.notify() {
            (c: Contact) in
            //...
            return true
        }
    }
}

Disclaimer: I am the author of Scapix Language Bridge.

Related