Swift'i C ++ ile karıştırabilir miyim? Objective-C .mm dosyaları gibi


131

.M dosyalarımı .mm olarak değiştirdim ve C ++ kullandım. Swift ile aynı şeyi yapmanın bir yolu var mı?

Yanıtlar:


111

Hayır. .M'den .mm'ye geçtiğinizde, aslında Objective-C'den Objective-C ++ adlı farklı bir dile (pek çok ince farklılığı olan) geçersiniz. Yani gerçekten C ++ kullanmıyorsunuz; Çoğu C ++ 'yı girdi olarak kabul eden Objective-C ++' yı kullanıyorsunuz (C ++ 'nın çoğunu kabul ettiği ancak tüm C'yi girdi olarak kabul etmediği gibi). Tam olarak C ++ olmadığını söylediğimde, adında bir değişken içeren bir C ++ dosyası düşününnil (yasal C ++ olan) ve ardından bunu Objective-C ++ olarak derlemeye çalışın.

Swift'in ilişkisi aynı değil. C veya C ++ 'nın bir üst kümesi değildir ve ikisini de doğrudan bir .swiftdosyada kullanamazsınız .

"Swift'i Kakao ve Objective-C ile Kullanmak" bize şunları da söyler:

C ++ kodunu doğrudan Swift'e aktaramazsınız. Bunun yerine, C ++ kodu için bir Objective-C veya C sarmalayıcı oluşturun.


93
Aslında oldukça can sıkıcı - C / C ++ kod tabanlarını içeren Cocoa uygulamaları ile hepimiz artık 3 dilde yazılmış projeleri sürdürmek zorundayız ....
Jay

6
Objective-c ++ 'nın farklı bir dil olmadığını, ancak c ++ ve Objective-c farkının bir karışımı olduğunu öneriyorum, ancak hala orada
amar

1
"Sıfır" yasal C ++ nasıldır? Böyle bir şey yok (en azından standart c ++ 'da) Lütfen başka bir örnek verin
rewolf

3
Ancak ObjC ile .mmdosyalarınıza gidebilir ve (neredeyse) bitmiş olabilirsiniz. Swift ile öyle değil.
chakrit

6
@rewolf, onun adında bir değişken anlamı var nilgibiint nil
Luke

165

Bu karışıklık, gerçekte bu türden hiçbir şey yapmadığında, yalnızca bir dosya uzantısını 'den' .me değiştirmenin .mmdilleri köprülemek için ihtiyacınız olan tek şey olduğu varsayımından kaynaklanıyor olabilir . Bu değildir .mmile sürtünmeyi neden olduğu .cppo, .hpozitif bir olmamalıdır başlık C++başlığı.


Aynı proje: Evet.

In aynı projede, sen mutlulukla karıştırabilirsiniz C , C ++ , Objective-C , Objective C ++ , Swift ve hatta Meclis .

  1. ...Bridging-Header.h: C , Objective-C ve Objective-C ++ ' ı Swift'e maruz bırakırsınız Bu köprüyü kullanarak
  2. <ProductModuleName>-Swift.h: Ortaya otomatik sizin Swift ile işaretlenmiş sınıfları @objciçin Objective-C
  3. .h: C , ++ ya da değil, Objective ya da değil tüm çeşitleri için belirsiz bir şekilde kullanıldıkları için bu zor kısımdır . Bir zaman .htek içermiyor C ++ anahtar gibi class, bu eklenebilir ...Bridging-Header.hve karşılık gelen işlev ne olursa olsun gösterecektir .c ya .cpp da beyan işlevleri. Aksi takdirde, bu başlık ya saf bir C ya da Objective-C API ile sarmalanmalıdır .

Aynı dosya: Hayır.

In aynı dosyanın, aynı olarak tüm 5. karştramazsnz kaynak dosyası :

  1. .swift: Eğer olamaz mix Swift şeyle
  2. .m: Karıştırabilir Objective-C ile C . ( @Vinzzz )
  3. .mm: Objective-C'yi C ++ ile karıştırabilirsiniz . Bu köprü Objective-C ++ ' dır . ( @Vinzzzz) ).
  4. .c: saf C
  5. .cpp: C ++ ve Assembly ( @Vality ) karıştırabilirsiniz
  6. .h: her yerde ve belirsiz C , C ++ , Objective-C veya Objective-C ++ , yani cevap buna bağlıdır.

Referanslar


1
Düzeltme: Aynı .m kaynak dosyasında, Objective-C katı bir C üst kümesidir, Objective-C ve C'yi karıştırabilirsiniz ...
Vinzzz

1
Sorun değil, yanıt doğru olduğu sürece krediyi umursamıyorum bile;) BTW, .mm Objective-C ve C ++ ' yı karıştırmak içindir (C ve C ++ ismine rağmen iki farklı şeydir )
Vinzzz

1
Nesnel C'den farklı olarak, C ++ 'nın bir C üst kümesi olmadığından, bir .cpp dosyasında hem C hem de C ++' yı karıştıramazsınız. Yalnızca C ++ ve derleme.
Vality

1
Swift dosyalarını Objective-C / C ++ dosyasında göstermeye çalışırken bu iyi ayrıntılı cevabın pek yardımcı olmadığını düşünen biri olursa (Xcode, Swift başlık dosyasının bulunamadığından şikayet ediyor). Ben ihtiyaç duyulduğu anlaşılmıştır ithalat "ÜrünAdı / ProductModuleName-Swift.h" benim Objective-C / C ++ kaynak dosyada. Bunu biraz gömülü buldum: developer.apple.com/library/ios/documentation/Swift/Conceptual/…
AeroBuffalo

İyi bir nokta. Bu dilleri karıştıran bir çalışma projesi için, stackoverflow.com/a/32546879/218152 adresine bakın .
SwiftArchitect

72

C ++, Objective C ve Swift kodunun nasıl karıştırılacağını gösteren basit bir Xcode 6 projesi yazdım:

https://github.com/romitagl/shared/tree/master/C-ObjC-Swift/Performance_Console

Özellikle örnek, Swift'den bir Hedef C ve bir C ++ işlevi çağırıyor.

Anahtar, ortak bir Project-Bridging-Header.h başlığı oluşturmak ve Objective C başlıklarını oraya koymaktır.

Lütfen projeyi eksiksiz bir örnek olarak indirin.


Bu Gian için teşekkürler!
Jason Elwood

Bu örnek için teşekkürler, ancak #import "CPlusPlus.h" dosyasını ObjCtoCPlusPlus.mm'den ObjCtoCPlusPlus.h dosyasına taşımak istersem, derleyici şu hatayı döndürür: <unknown>: 0: hata: köprüleme başlığı içe aktarılamadı ' /Users/Ale/Downloads/shared-master/C-ObjC-Swift/Performance_Console/Performance_Console/Performance_Console-Bridging-Header.h 'Bu içe aktarma üstbilgi dosyasına taşımak mümkün mü?
Alessandro Pirovano

@API: Hayır, noktayı kaçırıyorsun. ObjCtoCPlusPlus.h/ ".mm", yalnızca C ++ koduna bir Ob-C arabirimi sağlamak amacıyla mevcuttur - burada gerekli bir bileşen olan köprüdür. İçermeleri oldukları yerde bırakın ve ObjCtoCPlusPlus.…erişmeniz gereken her C ++ yöntemi için dosyalara bir yöntem ekleyin . Sen üzerine okumak iyi edersin sourcemaking.com/design_patterns/adapter
Slipp D., Thompson'a

Örneğinizi indirdim ve sınıfın örnek olarak sunduğu STATIC işlevi için harika, ancak örneği dışarıdan kullanılacak statik olmayan ek bir işlev için uyarlayamıyorum ... Bu da mümkün mü? (C ++ ödevimi onlarca yıl önce yaptım ... Şu anda kutunun en keskin kalemi değilim)
Isaac

31

Aradaki Objective-C dosyasını da atlayabilirsiniz . .Cpp kaynak dosyasıyla bir C başlık dosyası eklemeniz yeterlidir. Başlık dosyasında yalnızca C bildirimleri bulunur ve kaynak dosyada herhangi bir C ++ kodu bulunur. Ardından, C başlık dosyasını ** - Bridging-Header.h içine ekleyin.

Aşağıdaki örnek, bir C ++ nesnesine (struct Foo) bir işaretçi döndürür, böylece Swift, küresel alanda tanımlanmış yapı Foo yerine bir COpaquePointer'da depolayabilir.

Foo.h dosyası (Swift tarafından görülür - köprüleme dosyasına dahil edilir)

#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 kaynak dosyasının içinde (Swift tarafından görülmez):

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

1
Bu cevap hak yolu daha upvotes. Gerçekten kullanışlı.
rsp1984

Bu, üstbilgiyi başlık dosyasının kendisinde extern "C"yer almak yerine içerdiği yere sardığımı ilk kez görüyorum #ifdef. Parlak!
dcow

27

Swift, Objective-C ve C ++ kullanarak küçük bir örnek proje yaptım. İOS'ta OpenCV dikişinin nasıl kullanılacağına dair bir demo. OpenCV API C ++ olduğundan, onunla doğrudan Swift üzerinden konuşamayız. Uygulama dosyası Objective-C ++ olan küçük bir sarmalayıcı sınıf kullanıyorum. Başlık Swift doğrudan bu konuşabilirsiniz böylece dosya, Objective-C temiz. Swift'in etkileşime girdiği başlıklara C ++ - ish dosyalarını dolaylı olarak içe aktarmamaya dikkat etmelisiniz.

Proje burada: https://github.com/foundry/OpenCVSwiftStitch


Sanırım bu, Swift ile bir 3. parti kütüphane KudanCV kullanmaya çalışırken karşılaştığım bir soruna cevap veriyor. Köprüleme başlığım, C ++ kitaplıklarından veya dosyalarından olduğunu tahmin ettiğim <memory> <strings> ve <vectors> aktarımlarını içeren .h dosyalarını içe aktarıyor, sonuç olarak Swift kodum derlenmeyecek. Birisi bana bununla ilgili bir yol olup olmadığını söyleyebilirse ... veya tüm kodumu Objective-C
Rocket Garden'da

1
@RocketGarden - KudanCV başlık dosyası C ++ 'dır. Örnek sarmalayıcı sınıfımla aynı şekilde çalışan bir sarmalayıcı yazabilirsiniz. VEYA uygulamanızın KudanCV ile objektif-C ++ (Objective-C başlıklarıyla) konuşması gereken kısımlarını yeniden yazarsınız. Projenizin KudanCV ile ilgili olmayan kısımlarını yeniden yazmanıza gerek kalmaz.
dökümhane

Bunun için teşekkürler, bunu yaklaşık 5 dakika sonra fark ettim, ancak başkaları için kayıt altına almak faydalı.
Rocket Garden

13

İşte benim C ++ / hızlı iletişimini otomatikleştirmek için bir clang aracı denemem. C ++ sınıflarını swift'ten alabilir, C ++ sınıfından miras alabilir ve hatta swift'te sanal yöntemleri geçersiz kılabilirsiniz.
Hızla dışa aktarmak istediğiniz C ++ sınıfını ayrıştıracak ve Objective-C / Objective-C ++ köprüsünü otomatik olarak oluşturacaktır.

https://github.com/sandym/swiftpp




4

Hayır, tek bir dosyada değil.

Ancak Swift Projelerinde statik bir kitaplığa veya çerçeveye ihtiyaç duymadan C ++ kullanabilirsiniz. Başkalarının da söylediği gibi, anahtar, "C" haricindeki numara ile C uyumlu olarak işaretlenmiş C uyumlu C ++ başlıklarını # içeren bir Objective-C köprüleme başlığı oluşturmaktır .

Eğitim videosu: https://www.youtube.com/watch?v=0x6JbiphNS4


2

Diğer cevaplar biraz yanlış. Aslında aynı dosyada Swift ve [Objective-] C [++] 'yi karıştırabilirsiniz, ancak tam olarak beklediğiniz şekilde olmasa da.

Bu dosya (c.swift) hem swiftc c.swiftve hem de ile geçerli bir yürütülebilir dosyaya derlenirclang -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;
}
// */

Örnek kodunuz C ++ 'da değil. Bir <iostream> örneği IMHO ile devam etseniz iyi olur.
kakyo

2

Bir numara (birçok) şudur:

Köprüleme obj-c ++ dosyanız için ayrı bir başlığa ihtiyacınız var ...

Normalde birinin yaptığı gibi aynı .mm dosyasına @interface ve @implementation atamazsınız.

Yani köprü başlık dosyanızda

#import "Linkage.hpp"

Linkage.hpp, Bağlantı ve Bağlantı için @ arayüzüne sahiptir. Mm, .mm için @ uygulaması vardır.

Ve sonra

... aslında yok Linkage.hpp #include "yourCpp.hpp".

Yalnızca koymak #include "yourCpp.hpp", Linkage.mm dosyasında değil Linkage.hpp dosyasında.

Çoğu çevrimiçi örnekte / öğreticide, yazar, @interface ve @implementation öğelerini, genellikle birinin yaptığı gibi aynı .mm dosyasına koyar.

Bu, çok basit cpp köprüleme örneklerinde çalışacaktır, ancak,

Problem şu:

yourCpp.hpp'nizin kesinlikle yapacağı herhangi bir c ++ özelliği varsa (ilk satır gibi #include <something>), o zaman işlem başarısız olur.

Sadece Ama eğer yok olması #include "yourCpp.hpp"Bağlantı içinde başlık dosyası ( 's ince belli ki sen gerekir,, mm dosyasında sahip olmak) - çalışıyor.

Yine, bu maalesef tüm süreçte sadece bir ipucu.


1

Bunun herkes için yararlı olması durumunda, önemsiz bir Swift komut satırı yardımcı programından basit bir C ++ statik kitaplığı çağırma konusunda kısa bir eğitimim de var. Bu, kodun konsept parçasının gerçekten açık bir kanıtıdır.

Hiçbir Objective-C dahil değil, sadece Swift ve C ++. Bir C ++ kitaplığındaki kod, harici "C" bağlantısına sahip bir işlevi uygulayan bir C ++ sarıcı tarafından çağrılır. Bu işleve daha sonra köprüleme başlığında başvurulur ve Swift'den çağrılır.

Bkz. Http://www.swiftprogrammer.info/swift_call_cpp.html


1

Resmi kaynakta SE-0038'e bir bağlantı sağlıyorum. Bu bağlantı , Swift Programlama Dili'nde değişiklik ve kullanıcı tarafından görülebilen geliştirmeler için teklifler sunar.

Bugünkü durum, bunun kabul edilmiş ancak henüz planlanmamış özellik isteği olmasıdır.

Bu bağlantı, bu özelliği arayan herkesi doğru yönde yönlendirmeyi amaçlamaktadır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.