Objective-C++ and Swift - nested structs in bridging header

360 Views Asked by At

Please help me with the following issue. I am using the swift argument parser library https://github.com/apple/swift-argument-parser

Suppose I have this swift code in some swift file:

@objc public class Math: NSObject, ParsableCommand {
    static var configuration = CommandConfiguration(
        abstract: "A utility for performing maths.",
        subcommands: [Add.self],
        defaultSubcommand: Add.self)
}
    
extension Math {
    struct Add: ParsableCommand {
        static var configuration = CommandConfiguration(abstract: "Print the sum of the values.")        
        mutating func run() {
            print("0")
        }
    }
}

` and I want to call to an objective-c++ function named "func" with an argument which is of type Math.Add like so from main.swift file:

var status: Int32 = 0
do {
    // try to parse application arguments
    var args = try Math.parseAsRoot()
    switch args {
        case let args as Math.Add:
            status = func(args)
        default:
            try args.run()
        }
} catch {
    //Some code...
}

What should be the signature of the function and how the bridging-header files should look like? I made the signature be:

extern "C" int func(Math.Add *args);

And my bridging header is like so:

#ifndef __BRIDGING_HEADER_H__
#define __BRIDGING_HEADER_H__



@class Math;


#ifdef __cplusplus
   extern "C" {
#endif
   int func(Math.Add  *args);
#ifdef __cplusplus
    }
#endif

#endif /* __BRIDGING_HEADER_H__ */

but is doesn't work and the bridging header doesn't compile (Xcode writes the error: Interface type 'Math' cannot be passed by value; did you forget * in 'Math'?

1

There are 1 best solutions below

0
On

Objective-C(++) doesn't support nested types, what you can do if you want to keep the nested structure on Swift, is to export a non-nested type for Objective-C:

extension Math {
    @objc(Math_Add) // or MathAdd, or whatever name you like
    struct Add: ParsableCommand {

, which can then be referenced in your header:

int func(Math_Add  *args);

As a side note, I would also change the name of the func function to something that doesn't collide with Swift keywords. Even if you'll be able to call it, it will be confusing for other readers of your code.