Can I have Swift, Objective-C, C and C++ files in the same Xcode project?

前端 未结 1 2112
春和景丽
春和景丽 2020-11-28 01:01

Can all 4 languages be used in the same project at all, and if so how?

There are similar questions in the flavor: Can I mix Swift with C++? Like the Objecti

相关标签:
1条回答
  • 2020-11-28 01:32

    YES.

    You can mix Swift, C, C++, Objective-C & Objective-C++ files in the same Xcode project.

    C

    // Declaration: C.h
    #ifndef C_h
    #define C_h
    #ifdef __cplusplus
    extern "C" {
    #endif
        void hello_c(const char * name);
    #ifdef __cplusplus
    }
    #endif
    #endif /* C_h */
    
    // Definition: C.c
    #include "C.h"
    #include <stdio.h>
    void hello_c(const char * name) {
        printf("Hello %s in C\n", name);
    }
    

    C++

    // Declaration: CPP.hpp
    #pragma once
    #include <string>
    class CPP {
    public:
        void hello_cpp(const std::string& name);
    };
    
    // Definition: CPP.cpp
    #include "CPP.hpp"
    #include <iostream>
    using namespace std;
    void CPP::hello_cpp(const std::string& name) {
        cout << "Hello " << name << " in C++" << endl;
    }
    

    Objective-C wrapper for C++

    // Declaration: CPP-Wrapper.h
    #import <Foundation/Foundation.h>
    @interface CPP_Wrapper : NSObject
    - (void)hello_cpp_wrapped:(NSString *)name;
    @end
    
    // Definition: CPP-Wrapper.mm
    #import "CPP-Wrapper.h"
    #include "CPP.hpp"
    @implementation CPP_Wrapper
    - (void)hello_cpp_wrapped:(NSString *)name {
        CPP cpp;
        cpp.hello_cpp([name cStringUsingEncoding:NSUTF8StringEncoding]);
    }
    @end
    

    Objective-C

    // Declaration: Objective-C.h
    #import <Foundation/Foundation.h>
    @interface Objective_C : NSObject
    - (void)hello_objectiveC:(NSString *)name;
    @end
    
    // Definition: Objective-C.m
    #import "Objective-C.h"
    @implementation Objective_C
    - (void)hello_objectiveC:(NSString*)name {
        printf("Hello %s in Objective-C\n", [name cStringUsingEncoding:NSUTF8StringEncoding]);
    }
    @end
    

    Objective-C++

    // Declaration: Objective-CPP.h
    #import <Foundation/Foundation.h>
    @interface Objective_CPP : NSObject
    - (void)hello_objectiveCpp:(NSString *)name;
    @end
    
    // Definition: Objective-CPP.mm
    #include <iostream>
    #import "Objective-CPP.h"
    using namespace std;
    @implementation Objective_CPP
    - (void)hello_objectiveCpp:(NSString *)name {
        cout << "Hello " << [name cStringUsingEncoding:NSUTF8StringEncoding] << " in Objective-C++\n";
    }
    @end
    

    Swift

    // Declaration & definition: Swift.swift
    func hello_swift(_ name: String) {
        print("Hello \(name) in Swift")
    }
    

    Bridging-Header.h

    Cannot import CPP.hpp header file, not because of it's naming convention, but because it contains the class keyword.

    #import "C.h"
    #import "CPP-Wrapper.h"
    #import "Objective-C.h"
    #import "Objective-CPP.h"
    

    Invocation from Swift

    // Invoke C
    hello_c("World".cStringUsingEncoding(NSUTF8StringEncoding))
    
    // Can't Invoke C++ without a wrapper
    // CPP().hello_cpp("World".cStringUsingEncoding(NSUTF8StringEncoding))
    // Invoke C++ through Objective-C
    CPP_Wrapper().hello_cpp_wrapped("World")
    
    // Invoke Objective-C
    Objective_C().hello_objectiveC("World")
    
    // Invoke Objective-C++
    Objective_CPP().hello_objectiveCpp("World")
    
    // Invoke Swift
    Swift().hello_swift("World")
    

    .h (Headers)

    (See item 3 in this Stack Overflow answer)

    .h: this is the tricky part, since they are ambiguously used for all flavors of C, ++ or not, Objective or not. When a .h does not contain a single C++ keyword, like class, it can be added to the ...Bridging-Header.h, and will expose whatever function the corresponding .c or .cpp functionalities it declares. Otherwise, that header must be wrapped in either a pure C or Objective-C API.

    Output

    Hello World in C
    Hello World in C++
    Hello World in Objective-C
    Hello World in Objective-C++
    Hello World in Swift
    

    Comments

    Cy-4AH:

    Yes. You only need wrap C++ into C or Objective-C to use in Swift.

    Tommy

    Indeed, I have a project that does exactly that. C++ for the thrust of the abstract cross-platform model stuff with some C parts underneath; Objective-C to wrap the C++ classes for Swift purposes, Swift to bind all that to a subclass of NSDocument, with some custom views that interrogate the C stuff.

    MaddTheSane

    Added the extern "C" wrapper as per your excellent suggestion. To invoke the C method void hello_c(const char * name) from C++ method hello_cpp(const std::string& name), add #include "C.h" and call hello_c(name.c_str());.

    Keith Adler

    The new SO-32541268: Now with parameters!


    ► Find this solution on GitHub and additional details on Swift Recipes.

    0 讨论(0)
提交回复
热议问题