2

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.

The Dreams Wind
  • 8,416
  • 2
  • 19
  • 49
El_Loco
  • 1,716
  • 4
  • 20
  • 35

2 Answers2

1

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.

The Dreams Wind
  • 8,416
  • 2
  • 19
  • 49
  • Thanks a lot! I accidentally looked on another header file also. So used the incorrect function name. Silly mistake. I also had to link to some `libc++.tbd`. I got that from the example, I guess that contain some basic c++ stuff. Now it works. – El_Loco Aug 16 '22 at 13:59
0

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.

Boris Rasin
  • 448
  • 4
  • 12