Подтвердить что ты не робот

Могу ли я иметь файлы Swift, Objective-C, C и С++ в одном проекте Xcode?

Можно ли использовать все 4 языка в одном проекте, и если да, то как?

В аромате есть похожие вопросы: Можно ли смешивать Swift с С++? Как и файлы Objective - C.mm, на которые принят принятый ответ.

Используя Bridging Header адекватно, .h, которые не содержат операторов C++, Objective-C wrappers, когда .h содержат файлы C++, .mm для фактической упаковки классов C++ и .swift, могут ли 4 языка (5, если вы включаете Objective-C++) сборку и ссылку в один исполняемый файл?


4b9b3361

Ответ 1

ДА.

Вы можете смешивать файлы Swift, C, C++, Objective-C и Objective-C++ в том же проекте Xcode.

С

// 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);
}

С++

// 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 оболочка для С++

// 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

Невозможно импортировать заголовочный файл CPP.hpp не из-за его соглашения об именах, а из-за того, что он содержит ключевое слово class.

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

Вызов из 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(Заголовки)

(См. пункт 3 в этот ответ)

.h: это сложная часть, поскольку они неоднозначно используются для всех ароматов C, ++ или нет, Objective или нет. Когда .h не содержит одно ключевое слово С++, например класс, оно может быть добавлено в... Bridging-Header.h и будет раскрывать любую функцию, соответствующую соответствующим .c или .cpp-функциям, которые она объявляет. В противном случае этот заголовок должен быть обернут либо чистым C, либо Objective-C API.

Выход

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

Комментарии

Cy-4AH:

Да. Вам нужно только обернуть C++ в C или Objective-C для использования в Swift.

Tommy

В самом деле, у меня есть проект, который делает именно это. C++ для тяги абстрактной кросс-платформенной модели с некоторыми C частями внизу; Objective-C, чтобы обернуть классы C++ для целей Swift, Swift, чтобы связать все это с подклассом NSDocument, с некоторыми пользовательскими представлениями, которые опросили материал C.

MaddTheSane

Добавлена ​​обертка extern "C" в соответствии с вашим превосходным предложением. Чтобы вызвать метод C void hello_c(const char * name) из С++ метода hello_cpp(const std::string& name), добавьте #include "C.h" и вызовите hello_c(name.c_str());.

Кейт Адлер

Новый SO-32541268: Теперь с параметрами!


► Найдите это решение на GitHub и дополнительную информацию о Swift Рецепты.

Ответ 2

Я пробовал это для некоторой библиотеки C, которую я хочу включить в мой проект swift... и при записи hello_c в мой файл swift компилятор выдает мне эту ошибку:

Дубликат символа _hello_c в: /Users/.../mpfit.o/Users/../Fitting.o ld: 1 дубликат символа для архитектуры x86_64 clang: error: сбой команды компоновщика с кодом выхода 1 (используйте -v, чтобы увидеть призывание)

Я не понимаю, почему? Я объявил функцию в файле c, просто чтобы попробовать :)