2016-07-08 16 views
7

Üçüncü taraf geliştiricilere derlediğimiz ve dağıttığımız bir Swift Framework'üm var. Projeye bazı C kodları eklemek istiyorum, ancak çalışmayı başarabilmemin tek yolu, C başlığını çerçevemin başlığına getirip C başlığını halka olarak ayarlamak. Bu, C kodunun tamamını istediğimiz şey olmayan 3. taraf geliştiricilere sunar. "Bu tekniği kullanarak inşa etmek herhangi çerçeveler tüketiciler de sahip olacak unutmayın edilir https://spin.atomicobject.com/2015/02/23/c-libraries-swift/C kodu Swift Framework'e nasıl derlerim?

Ancak bu yöntemin uyarı: çevrimiçi bunu nasıl için bulabilirsiniz

Her şey bir bu yöntemin varyasyon Modülü kendi Swift arama yollarına eklemek. " Bunu denedik ve 3. taraf geliştiricilerimizin, C başlığına işaret ettiğimiz modül olan Missing required module 'CGeodesic' hatalarını almasını sağladık.

Kodu özel olarak korurken C kodunu doğrudan çerçevemize nasıl derleyebiliriz ve 3. taraf geliştiricilerin çalışmasını sağlamak için yapı ayarlarını değiştirmelerini istemeyiz? Bu altmodülleri bizim projemizde kurmak zorunda kalmıyorum, ancak günün sonunda doğrudan tek bir düz çerçeve ikiliye, dinamik bağlantılara veya arama yollarına veya bunun gibi herhangi bir şeye derlenmesini istiyorum.

düzenleme


projesi C kodu yan yana Swift kodu ile.

  • Geodezik/
    • Geodesic.h
    • Geodesic.c
    • Geodesic.swift

: Şöyle Projemdeki bir alt dizin var Swift dosyası, çalışmayı daha temiz hale getirmek için C kodunu sarar. Ben de bu dizinde bir module.modulemap dosyası vardı, ama daha önce çalışmadı dediğim gibi. C kodumuzu Swift kodumla yan yana tutmayı tercih ederim ama bu sorunu çözmek için bunu vermeye hazırım.

+0

Geçerli ayarlarınız nedir? C kodu Swift koduyla yan yana mı? – zneak

+0

https://developer.apple.com/library/ios/documentation/Swift/Conceptual/BuildingCocoaApps/MixandMatch.html. Bu yardımcı olur mu? C kodu Objective-C'dir ve C ve Swift karışımında bir çerçeve yazabilir gibi görünür ve kullanıcılara tek bir dilde yazılmış gibi görünür. Henüz kendim denemedim. – OmniProg

+0

@OmniProg, şu anda yaptığımız şey bu. Bu yöntemle ilgili problem, bu başlıkların tümünü kamuya açık bir şekilde ortaya çıkarmasıdır. Bu, kaçınmaya çalıştığımız şeydir. – user1084447

cevap

14

Sorununuzu yalnızca yeniden yazmak için: Temel olarak C kodunu Swift içine sarmak ve kapsüllenmiş C koduna doğrudan erişimi engellemek istiyorsunuz. Bu, hem Swift hem de Objective-C'den erişimi engellemek anlamına gelir.

Bu mümkündür, ancak derleme işleminizde ve bazı işlemlerde bazı ayarlamalar yapılmalıdır. Çerçeveler içinde

C Swift Interop'un

Eğer Swift de sarmak istiyorum Herhangi C kodu ya şemsiye başlığındaki veya modül haritaları kullanarak yoluyla derleme sırasında kamu olması gerekiyor. Burada önemli olan: derleme zamanı. Çerçevelerin bütünlük kontrolleri yoktur, bu da onlara sonradan işlemeyi uygulayabileceğiniz anlamına gelir (örneğin, lipo ile yağ ikili bir çerçeve oluşturun). Ve burada yapmamız gereken şey bu.şemsiye başlığına tüm C başlık bağımlılıkları koyma

yerine yapı hazırlama

ayrıca module.modulemap dosya içine koyabilirsiniz. Bunun bir avantajı vardır: Başlıklarınızı Headers Yapı Aşamasında özel yapabilirsiniz.

Bu nedenle, projede bir module.modulemap dosyası oluşturmak ve (xcconfig dosyalarında MODULEMAP_FILE) Packaging bölümünde ayarlama Module Map File Build'a, mesela $(SRCROOT)/MyFramework/module.modulemap kendisine yolu ayarlayın. Şimdiye kadar

# module.modulemap 

framework module MyFramework { 

    umbrella header "MyFramework.h" 

    export * 
    module * {export *} 

    # All C Files you want to wrap in your Swift code 

    header "A.h" 
    header "B.h" 
} 

çok iyi:

Sizin module.modulemap dosyası aşağıdaki içeriğe sahip olmalıdır. Artık kodunuzu oluşturup hem Swift hem de Objective-C'den erişebilmeniz gerekir. Tek sorun: C başlık dosyalarınıza Swift ve Objective-C'de hala erişebilirsiniz.

Postprocess

nihai Framework bir göz tüm özel başlık dosyaları MyFramework.framework/PrivateHeaders klasöre kopyalanmış olduğunu göreceksiniz paket varsa. Bu, onlara Objective-C'de #import <MyFramework/A.h> aracılığıyla erişebileceğiniz anlamına gelir.

Swift'de C koduna hala erişebilirsiniz, çünkü üstbilgi dosyalarını MyFramework.framework/Modules/module.modulemap'a kopyalanan module.modulemap dosyasına koyarız.

Neyse ki, biz sadece son işlemenin biraz bu iki sorunların kurtulabilirsiniz:

  1. çerçeve demetinden PrivateHeaders klasörü çıkarın.
  2. Ayrı bir modül oluşturun ve tüm header "XYZ.h" ifadelerini kaldırın, ör. Adı public.modulemap.
  3. bir Run Script Yapı Faz bütün bunlar koyun

İşte kamu modulemap var:

: Eğer çerçevenin inşa aşamalarının sonuna eklemek gerekir

# public.modulemap 

framework module MyFramework { 

    umbrella header "MyFramework.h" 

    export * 
    module * {export *} 

    # No more C Headers here 
} 

Ve çalıştırmak komut

# Delete PrivateHeaders folder 
rm -rf ${TARGET_BUILD_DIR}/${PRODUCT_NAME}${WRAPPER_SUFFIX}/PrivateHeaders 

# Remove module.modulemap file 
rm ${TARGET_BUILD_DIR}/${PRODUCT_NAME}${WRAPPER_SUFFIX}/Modules/module.modulemap 

# Copy public.modulemap file and rename it to module.modulemap 
cp ${SRCROOT}/test/public.modulemap ${TARGET_BUILD_DIR}/${PRODUCT_NAME}${WRAPPER_SUFFIX}/Modules/module.modulemap 

# Append the Swift module so you can access you Swift code in Objective-C via @import MyFramework.Swift 
echo "module ${PRODUCT_NAME}.Swift { header \"${PRODUCT_NAME}-Swift.h\" }" >> ${TARGET_BUILD_DIR}/${PRODUCT_NAME}${WRAPPER_SUFFIX}/Modules/module.modulemap 

Bu yardımcı olur umarım!

+0

Mükemmel çalışıyor! Teşekkür ederim! – user1084447

+3

Bu karmaşık bir soruna mükemmel bir cevaptır, teşekkürler. –

+0

Bu cevap elbette inanılmaz, @JensMeder, teşekkürler.tek bir şey - belki de * basit durumun * kısa bir ekini ekleyebilirsiniz, burada * doğrudan erişimi engellemek için * gerek yoktur. Bu cevabı netleştirebilir. Bahse girerim bu çok yardımcı olur. (Www üzerindeki tüm eski yazılar zamanla kayboldu! :)) – Fattie

1

Önerilmemesine rağmen bir çözüm var. C başlık kullanmak yerine .Swift dosyanızın içinde use @_silgen_name yapabilirsiniz.