ฉันเพิ่งเปลี่ยนไฟล์. m เป็น. mm และใช้ C ++ มีวิธีทำเช่นเดียวกันกับ Swift หรือไม่?
ฉันเพิ่งเปลี่ยนไฟล์. m เป็น. mm และใช้ C ++ มีวิธีทำเช่นเดียวกันกับ Swift หรือไม่?
คำตอบ:
ไม่เมื่อคุณเปลี่ยนจาก. m เป็น. mm คุณกำลังเปลี่ยนจาก Objective-C เป็นภาษาอื่น (ซึ่งมีความแตกต่างเล็กน้อย) ที่เรียกว่า Objective-C ++ ดังนั้นคุณจึงไม่ได้ใช้ C ++ จริงๆ คุณกำลังใช้ Objective-C ++ ซึ่งยอมรับ C ++ ส่วนใหญ่เป็นอินพุต (เช่นเดียวกับที่ C ++ ยอมรับ C ส่วนใหญ่ แต่ไม่ใช่ทั้งหมดเป็นอินพุต) เมื่อฉันบอกว่ามันไม่ใช่ C ++ ให้พิจารณาไฟล์ C ++ ที่มีตัวแปรชื่อnil
(ซึ่งเป็น C ++ ตามกฎหมาย) แล้วพยายามรวบรวมเป็น Objective-C ++
Swift ไม่มีความสัมพันธ์แบบเดียวกัน ไม่ใช่ชุดพิเศษของ C หรือ C ++ และคุณไม่สามารถใช้โดยตรงใน.swift
ไฟล์ได้
"การใช้ Swift กับ Cocoa และ Objective-C"ยังบอกเรา:
คุณไม่สามารถนำเข้ารหัส C ++ ไปยัง Swift ได้โดยตรง ให้สร้าง Objective-C หรือ C wrapper สำหรับโค้ด C ++ แทน
.mm
ไฟล์ของคุณและทำ (เกือบ) เสร็จ ไม่เป็นเช่นนั้นกับ Swift
nil
เช่นint nil
ความสับสนที่อาจมาจากสมมติฐานที่ว่าเพียงแค่เปลี่ยนนามสกุลไฟล์จาก.m
ที่จะ.mm
เป็นสิ่งที่คุณจำเป็นต้องสร้างสะพานเชื่อมภาษาเมื่อในความเป็นจริงมันไม่ทำอะไรเลยของการจัดเรียงที่ มันไม่ได้เป็น.mm
ที่ทำให้เกิดแรงเสียดทานกับ.cpp
มันเป็น.h
ส่วนหัวซึ่งจะต้องบวกไม่เป็นC++
ส่วนหัว
ในโครงการเดียวกันคุณสามารถผสมC , C ++ , Objective-C , Objective C ++ , Swiftและแม้แต่Assemblyได้อย่างมีความสุข
...Bridging-Header.h
: คุณเปิดเผยC , Objective-CและObjective-C ++เป็นSwiftโดยใช้บริดจ์นี้<ProductModuleName>-Swift.h
: exposes โดยอัตโนมัติของสวิฟท์ชั้นเรียนที่มีเครื่องหมาย@objc
เพื่อวัตถุประสงค์ -C.h
: นี่เป็นส่วนที่ยุ่งยากเนื่องจากมีการใช้อย่างคลุมเครือสำหรับทุกรสชาติของC , ++หรือไม่ก็ตามวัตถุประสงค์หรือไม่ เมื่อ a .h
ไม่มีคำหลักC ++คำเดียวเช่นclass
สามารถเพิ่มลงในคำหลัก...Bridging-Header.h
และจะแสดงฟังก์ชันที่เกี่ยวข้อง.c
หรือ .cpp
ฟังก์ชันที่ประกาศ มิฉะนั้นส่วนหัวดังกล่าวจะต้องถูกรวมไว้ในCบริสุทธิ์หรือObjective-C APIในไฟล์เดียวกันคุณไม่สามารถผสมทั้ง 5 ในไฟล์ต้นฉบับเดียวกันได้:
.swift
: คุณไม่สามารถผสมSwift ได้กับอะไรก็ได้.m
: คุณสามารถผสมObjective-CกับC ( @Vinzzz ).mm
: คุณสามารถผสมObjective-CกับC ++ได้ สะพานนี้เป็นวัตถุประสงค์-C ++ ( @Vinzzz )..c
: บริสุทธิ์C.cpp
: คุณสามารถผสมC ++ & Assembly ( @Vality ).h
: C , C ++ , Objective-CหรือObjective-C ++ ที่แพร่หลายและคลุมเครือดังนั้นคำตอบจึงขึ้นอยู่กับอ้างอิง
ฉันเขียนโครงการ Xcode 6 อย่างง่ายที่แสดงวิธีผสม C ++, Objective C และ Swift code:
https://github.com/romitagl/shared/tree/master/C-ObjC-Swift/Performance_Console
โดยเฉพาะอย่างยิ่งตัวอย่างเรียกใช้ Objective C และฟังก์ชัน C ++ จาก Swift
กุญแจสำคัญคือการสร้างส่วนหัวที่ใช้ร่วมกัน Project-Bridging-Header.h และใส่ส่วนหัว Objective C ไว้ที่นั่น
โปรดดาวน์โหลดโครงการเป็นตัวอย่างที่สมบูรณ์
ObjCtoCPlusPlus.h
/“ .mm` มีขึ้นเพื่อจุดประสงค์เดียวในการจัดหาอินเทอร์เฟซ Ob-C ให้กับโค้ด C ++ นั่นคือบริดจ์ซึ่งเป็นส่วนประกอบที่จำเป็นที่นี่ ปล่อยให้รวมไว้ที่ที่พวกเขาอยู่และเพิ่มวิธีการในObjCtoCPlusPlus.…
ไฟล์สำหรับแต่ละวิธี C ++ ที่คุณต้องการเข้าถึง คุณควรอ่านsourcemaking.com/design_patterns/adapter
คุณสามารถข้าม Objective-C ได้ด้วยระหว่างไฟล์. เพียงเพิ่มไฟล์ส่วนหัว C ด้วยซอร์สไฟล์. cpp มีเฉพาะการประกาศ C ในไฟล์ส่วนหัวและรวมรหัส C ++ ใด ๆ ในไฟล์ต้นฉบับ จากนั้นรวมไฟล์ส่วนหัว C ไว้ใน ** - Bridging-Header.h
ตัวอย่างต่อไปนี้ส่งคืนตัวชี้ไปยังวัตถุ C ++ (โครงสร้าง Foo) เพื่อให้ Swift สามารถจัดเก็บใน COpaquePointer แทนที่จะมีการกำหนด struct Foo ในพื้นที่ส่วนกลาง
ไฟล์ Foo.h (เห็นโดย Swift - รวมอยู่ในไฟล์ bridging)
#ifndef FOO_H
#define FOO_H
// Strictly C code here.
// 'struct Foo' is opaque (the compiler has no info about it except that
// it's a struct we store addresses (pointers) to it.
struct Foo* foo_create();
void foo_destroy(struct Foo* foo);
#endif
ภายในซอร์สไฟล์ Foo.cpp (ไม่เห็นโดย Swift):
extern "C"
{
#include "Foo.h"
}
#include <vector>
using namespace std;
// C++ code is fine here. Can add methods, constructors, destructors, C++ data members, etc.
struct Foo
{
vector<int> data;
};
struct Foo* foo_create()
{
return new Foo;
}
void foo_destroy(struct Foo* foo)
{
delete foo;
}
extern "C"
ตัดส่วนหัวในตำแหน่งที่รวมไว้แทนที่จะเป็น#ifdef
'ed ในไฟล์ส่วนหัว ยอดเยี่ยม!
ฉันเพิ่งทำโปรเจ็กต์ตัวอย่างเล็กน้อยโดยใช้ Swift, Objective-C และ C ++ เป็นการสาธิตวิธีใช้ OpenCV เย็บใน iOS OpenCV API คือ C ++ ดังนั้นเราจึงไม่สามารถพูดคุยโดยตรงจาก Swift ได้ ฉันใช้คลาส Wrapper ขนาดเล็กซึ่งไฟล์การใช้งานคือ Objective-C ++ หัวไฟล์สะอาด Objective-C เพื่อให้สวิฟท์สามารถพูดคุยกับนี้โดยตรง คุณต้องระวังอย่านำเข้าไฟล์ C ++ - ish โดยอ้อมไปยังส่วนหัวที่ Swift โต้ตอบด้วย
โครงการอยู่ที่นี่: https://github.com/foundry/OpenCVSwiftStitch
นี่คือความพยายามของฉันที่ใช้เครื่องมือส่งเสียงดังเพื่อทำให้การสื่อสาร C ++ / รวดเร็วโดยอัตโนมัติ คุณสามารถติดตั้งคลาส C ++ ได้อย่างรวดเร็วสืบทอดจากคลาส C ++ และแม้แต่ลบล้างเมธอดเสมือนได้อย่างรวดเร็ว
มันจะแยกวิเคราะห์คลาส C ++ ที่คุณต้องการส่งออกให้รวดเร็วและสร้างสะพาน Objective-C / Objective-C ++ โดยอัตโนมัติ
Swift ไม่สามารถทำงานร่วมกับ C ++ ได้โดยตรง คุณสามารถแก้ไขปัญหาได้โดยการห่อรหัส C ++ ด้วย Objective-C และใช้ Objective C wrapper ใน Swift
ไม่ใช่ไม่ใช่ในไฟล์เดียว
อย่างไรก็ตามคุณสามารถใช้ C ++ ใน Swift Projects ได้โดยไม่จำเป็นต้องมีไลบรารีแบบคงที่หรือเฟรมเวิร์ก เช่นเดียวกับคนอื่น ๆ กล่าวไว้กุญแจสำคัญคือการสร้างส่วนหัวของ Objective-C bridging ที่ # รวมส่วนหัว C ++ ที่เข้ากันได้กับ C ซึ่งทำเครื่องหมายเป็น C ที่เข้ากันได้กับเคล็ดลับ"C" {}ภายนอก
วิดีโอสอน: https://www.youtube.com/watch?v=0x6JbiphNS4
คำตอบอื่น ๆ ไม่ถูกต้องเล็กน้อย คุณสามารถผสมทั้ง Swift และ [Objective-] C [++] ในไฟล์เดียวกันได้แม้ว่าจะไม่เป็นไปตามที่คุณคาดหวัง
ไฟล์นี้ (c.swift) คอมไพล์เป็นไฟล์ปฏิบัติการที่ถูกต้องโดยมีทั้งswiftc c.swift
และclang -x objective-c c.swift
/* /* */
#if 0
// */
import Foundation
print("Hello from Swift!")
/* /* */
#endif
#include <stdio.h>
int main()
{
puts("Hello from C!");
return 0;
}
// */
เคล็ดลับอย่างหนึ่ง (จากหลาย ๆ คน) ก็คือ
คุณไม่สามารถโยน @interface และ @implementation ในไฟล์. mm เดียวกันได้เหมือนที่ปกติ
ดังนั้นในไฟล์ส่วนหัวเชื่อมต่อของคุณคุณมี
#import "Linkage.hpp"
Linkage.hpp มี @interface สำหรับ Linkage และ Linkage.mm มี @implementation สำหรับ. mm
แล้ว
คุณใส่เฉพาะ#include "yourCpp.hpp"
ไฟล์ Linkage.mm ไม่ใช่ในไฟล์ Linkage.hpp
ในตัวอย่าง / บทช่วยสอนออนไลน์จำนวนมากผู้เขียนเพียงแค่ใส่ @interface และ @implementation ไว้ในไฟล์. mm เดียวกันอย่างที่มักทำกัน
ซึ่งจะทำงานในตัวอย่างการเชื่อมต่อ cpp ที่เรียบง่าย แต่
ปัญหาคือ:
หาก yourCpp.hpp ของคุณมีคุณสมบัติ c ++ ใด ๆ ซึ่งมันจะแน่นอน (เช่นบรรทัดแรก#include <something>
) กระบวนการจะล้มเหลว
แต่ถ้าคุณเพียงแค่ไม่ได้มี#include "yourCpp.hpp"
ในการเชื่อมโยงส่วนหัวของไฟล์ (มันปรับให้มีไว้ในไฟล์ .mm อย่างเห็นได้ชัดคุณจะต้อง) - มันทำงาน
อีกครั้งนี่เป็นเพียงเคล็ดลับเดียวในกระบวนการทั้งหมด
ในกรณีนี้เป็นประโยชน์สำหรับทุกคนฉันยังมีบทช่วยสอนสั้น ๆ เกี่ยวกับการเรียกไลบรารีแบบคงที่ C ++ อย่างง่ายจากยูทิลิตี้บรรทัดคำสั่ง Swift เล็กน้อย นี่เป็นการพิสูจน์ชิ้นส่วนแนวคิดของรหัส
ไม่มี Objective-C เกี่ยวข้องเพียงแค่ Swift และ C ++ โค้ดในไลบรารี C ++ ถูกเรียกโดย C ++ wrapper ที่ใช้ฟังก์ชันที่มีลิงก์ "C" ภายนอก จากนั้นฟังก์ชันนั้นจะถูกอ้างอิงในส่วนหัวของการเชื่อมต่อและเรียกใช้จาก Swift
ฉันกำลังให้ลิงก์ไปยังSE-0038ในแหล่งข้อมูลอย่างเป็นทางการโดยอธิบายว่า นี่จะเก็บรักษาข้อเสนอสำหรับการเปลี่ยนแปลงและการปรับปรุงที่ผู้ใช้มองเห็นได้สำหรับภาษาการเขียนโปรแกรม Swift
สถานะ ณ วันนี้คือนี่คือคำขอคุณลักษณะที่ได้รับการยอมรับ แต่ยังไม่มีกำหนดเวลา
ลิงก์นี้มีไว้เพื่อคัดท้ายทุกคนที่กำลังมองหาคุณลักษณะนี้ในทิศทางที่ถูกต้อง