Структуры, вложенные в Objective-C и Swift, в заголовке моста

#swift #objective-c #bridging-header

#быстрый #objective-c #соединительный заголовок

Вопрос:

Пожалуйста, помогите мне со следующей проблемой. Я использую библиотеку синтаксического анализа аргументов swift https://github.com/apple/swift-argument-parser

Предположим, у меня есть этот код swift в каком-то файле swift:

 @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")
        }
    }
}
 

«и я хочу вызвать функцию objective-c с именем «func» с аргументом типа Math.Добавьте вот так из файла main.swift:

 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...
}
 

Какой должна быть сигнатура функции и как должны выглядеть файлы соединительных заголовков? Я сделал подпись:

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

И мой соединительный заголовок выглядит так:

 #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__ */
 

но is не работает, и связующий заголовок не компилируется (Xcode выдает ошибку: тип интерфейса ‘Math’ не может быть передан по значению; вы забыли * в ‘Math’?

Ответ №1:

Objective-C ( ) не поддерживает вложенные типы, что вы можете сделать, если хотите сохранить вложенную структуру в Swift, так это экспортировать не вложенный тип для Objective-C:

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

, на который затем можно ссылаться в вашем заголовке:

 int func(Math_Add  *args);
 

В качестве дополнительного замечания я бы также изменил имя func функции на что-то, что не противоречит ключевым словам Swift. Даже если вы сможете вызвать его, это будет сбивать с толку других читателей вашего кода.