Swift 6.3 veya üzeri sürümlerde, bir global işlevi @c ile işaretleyin, uyumluluk başlığını oluşturun, çağırıcıyı C olarak derleyin ve swiftc ile bağlayın. Bu anlatım, her sınırı gösteren küçük bir yerel Mac komut satırı programı oluşturur.

Okuyucu görevi spesifiktir: normal bir .c dosyasından bir Swift hesaplamasını çağırmak, o dosyayı Objective-C veya C++ olarak derlemeden. Swift'in resmi sürüm belgeleri, @c niteliğini Swift 6.3'te tanıtılan desteklenen C birlikte çalışabilirlik özelliği olarak tanımlar. Eski deneysel nitelikler hakkında tavsiyeleri takip etmeden önce yüklü derleyicinizi kontrol edin. Swift 6.3 Released

Bir Swift işlevini C'den çağrılabilir kılan nedir?

Üç parça uyumlu olmalıdır: C derleyicisinin okuyacağı bildirim, uygulamanın kullandığı çağırma kuralı ve bağlayıcıya sağlanan nesne dosyaları. Bir başlık ilk parçayı karşılar; eksik bir uygulamayı sağlayamaz veya mevcut bir işlevin ABI'sini değiştiremez.

@c niteliği, global bir Swift işlevine C çağırma kuralını verir ve imzasını C-temsil edilebilir türlerle kısıtlar. İsteğe bağlı bir nitelik argümanı, C adını seçer. Swift, karşılık gelen bildirimi oluşturulan uyumluluk başlığının C-uyumlu kısmında yayar. Bu davranışlar, uygulanan Swift Evolution önerisinde belirtilmiştir. C compatible functions and enums

Bu örnekte, arayüz bir C tam sayısını kabul eder ve döndürür. Sentetik hesaplama, bir görüntüleme yüzdesini sıfır ile 100 (dahil) aralığına sıkıştırır. Arabellekler, ayrılan sonuçlar veya koordine edilecek nesne ömrü yoktur. Bu, ilk derlemeyi derleme ve bağlama üzerine odaklı tutar.

Mac araç zincirini önce kontrol edin

Clang, bir macOS SDK'sı ve Swift 6.3 veya üzeri sürümüne sahip bir macOS geliştirme ortamına ihtiyacınız var. Apple, Xcode ile komut satırı araçlarını sağlar ve ayrıca ayrı bir Command Line Tools paketi sunar. Zaten Xcode'ınız varsa, Apple ayrı bir araç kurulumunun gerekli olmadığını söyler. Installing the command-line tools

Terminal'de bu kontrolleri çalıştırın:

xcode-select --print-path
xcrun --sdk macosx swiftc --version
xcrun --sdk macosx clang --version

Swift derleyici sürümünü doğrudan inceleyin. Daha eski bir derleyici, daha yeni bir SDK yüklü olsa bile @c özelliğini kazanmaz. Birden fazla Xcode sürümü varsa, Apple etkin sürümü Xcode > Settings > Locations > Command Line Tools bölümünden seçmeyi veya bir kabuk oturumu için DEVELOPER_DIR ile geçersiz kılmayı belgeler. Configuring command-line tools settings

Aşağıdaki komutlar, seçili geliştirme araçlarını çağırmak için xcrun kullanır. Apple, bu aracı keşif rolünü komut satırı derleme referansında belgelemiştir. Building from the Command Line with Xcode FAQ

Boş bir çalışma dizini oluşturun ve aşağıdaki her iki kaynak dosyayı içine kaydedin. Derleme komutlarını o dizinden çalıştırın. Bu, yerel Mac için yerel bir derlemedir; evrensel bir ikili oluşturmaz veya başka bir platformu yapılandırmaz.

Swift uygulamayı ve C çağırıcıyı yazın

Dışa aktarılan Swift işlevini tanımlayın

Bu tam Swift kaynak dosyasını Percent.swift olarak kaydedin:

@c(demo_clamp_percent)
public func clampPercent(_ value: CInt) -> CInt {
    if value < 0 {
        return 0
    }
    if value > 100 {
        return 100
    }
    return value
}

Swift adı clampPercent; C'ye bakan ad demo_clamp_percent'dir. CInt, C'nin int'ine eşlenir. Bu açık eşleşmeyi kullanmak, Swift Int'in C int anlama gelmediğini varsaymamayı sağlar: Swift Int için belgelenen eşleme ptrdiff_t'dur. C compatible functions and enums

İşlev değerleri karşılaştırır ve ya bir girişi ya da bir sabiti döndürür. Hesaplaması, yüzde aralığının dışındaki girdiler dahil hiçbir aritmetik taşma oluşturmaz. Dışa aktarılan ad üzerindeki önek, bu arayüzü daha büyük bir programdaki diğer işlevlerden ayırt etmek için bir örnek kuralıdır.

Bunu tam bir C programından çağırın

Bu dosyayı main.c olarak kaydedin. Derleme, dahil edilen başlığı oluşturacak:

#include <stddef.h>
#include <stdio.h>
#include "Percent-Swift.h"

int main(void) {
    const int inputs[] = {-12, 42, 140};
    const int expected[] = {0, 42, 100};
    const size_t count = sizeof inputs / sizeof inputs[0];

    for (size_t i = 0; i < count; ++i) {
        const int actual = demo_clamp_percent(inputs[i]);
        printf("%d -> %d\n", inputs[i], actual);
        if (actual != expected[i]) {
            fprintf(stderr, "Unexpected result at index %zu\n", i);
            return 1;
        }
    }
    return 0;
}

Üç girdi, alt sınırı, değiştirilmemiş bir değeri ve üst sınırı test eder. Program sonuçları açıkça kontrol eder ve bir uyuşmazlıkta sıfırdan farklı bir durum döndürür, bu yüzden çıktısı sadece bir sayı yazdıran bir gösterimden daha faydalıdır.

Başlığı oluşturun, C'yi derleyin ve programı bağlayın

İki dosyayı içeren dizinden bir kabukta bu sırayı çalıştırın. Her derleme adımı başarısız olursa sırayı durdurur:

(
    set -eu
    SDK_PATH="$(xcrun --sdk macosx --show-sdk-path)"

    xcrun --sdk macosx swiftc \
        -sdk "$SDK_PATH" \
        -parse-as-library \
        -module-name Percent \
        -emit-object Percent.swift \
        -emit-objc-header-path Percent-Swift.h \
        -o Percent.o

    xcrun --sdk macosx clang \
        -isysroot "$SDK_PATH" \
        -x c -std=c11 \
        -Wall -Wextra -Werror \
        -c main.c -o main.o

    xcrun --sdk macosx swiftc \
        -sdk "$SDK_PATH" \
        main.o Percent.o \
        -o percent-demo

    ./percent-demo
)

İlk komut Swift nesnesini ve uyumluluk başlığını üretir. Swift'in sürücüsü -emit-object'i nesne dosyası çıktısı olarak, -parse-as-library'yi ise betik yerine kütüphane kaynağı olarak ayrıştırma olarak tanımlar. Bu, çalıştırılabilir giriş noktasını C dosyasına bırakır. Swift compiler driver options

Tarihsel adına rağmen, -emit-objc-header-path ayrıca @c bildirimleri için uyumluluk başlığının C bölümünü de ister. Uygulanan öneri, bu bayrağı bu amaçla açıkça korur. Oluşturulan başlığı varsayıyorsal bir prototiple el ile değiştirmeyin. C compatible functions and enums

İkinci komut, belirleyici kaynak dili kontrolüdür. Clang, -x'i giriş dili seçimi olarak, -c'yi bağlama olmadan nesne dosyası üretimi olarak belgeler. Burada, -x c -std=c11 çağırıcıyı gerçek oluşturulan başlığı okurken C11 olarak derler. Clang command guide

Son derleyici çağrısı, her iki nesne dosyasını Swift sürücüsünü kullanarak bağlar. Swift'in kendi derleyici kılavuzu, daha düşük seviyeli bir bağlama komutunu el ile montaj yapmak yerine swiftc'ın dosyaları bağlamasını isteyeni önerir. Debugging the Compiler

Örnekteki dallardan türetilen beklenen çıktı:

-12 -> 0
42 -> 42
140 -> 100

Bu komutlar, alınan belgelerle karşılaştırıldı ancak burada yürütülmedi: araştırma ortamı Linux'tır ve ne swiftc ne de Clang mevcuttur. Yukarıdaki çıktı beklenen bir sonuçtur, rapor edilen bir Mac test çalışması değildir.

Mevcut kodunuzla eşleşen arayüzü seçin

Swift 6.3 veya üzeri sürümlerde yeni, küçük bir arayüz için, yukarıdaki oluşturulan başlık yaklaşımı bildirimi uygulamayla doğrudan bağlı tutar. Sürüm belgeleri ayrıca ikinci bir yönü de destekler: @c @implementation, zaten içe aktarılan bir C başlığında bildirilmiş bir işlevi uygular ve Swift imzaların eşleştiğini kontrol eder. Bu, mevcut bir C API'sinin arayüz sözleşmesi olarak kalması gerektiğinde yararlıdır. Swift 6.3 Released

Eğer çevreleyen proje zaten C++ üzerinden Swift çağırıyorsa, Swift'in oluşturulan C++ bağlamaları başka bir yol sunar. Genel Swift işlevleri, bir modül ad alanı içinde satır içi C++ işlevleriyle temsil edilir. Bir C çağırıcıya, küçük bir C'ye bakan bildirimi kullanıma sunan, C++ olarak derlenmiş ayrı bir bağdaştırıcı gerekecekti. C çeviri birimi, o bağdaştırının C başlığını dahil edecektir. Mixing Swift and C++

Böyle bir bağdaştırıcıda, extern \"C\" C++ bildiriminde veya tanımında C dili bağlamasını belirtir. Bir C++ başlığının içeriğini C sözdizimine dönüştürmez. C++ çalışma taslağı, bağlama belirtimlerini tanımlar ve dil bağlamasını sıradan bildirimlerden ayırır. C++ working draft: Linkage specifications

Bu eğitim için, @cyi destekleyen bir derleyiciye yükseltmek, doğrudan desteklenen yoldur. Öneri, @_cdecl'i deneysel öncüsü olarak tanımlar; o eski yazımı yeni bir örneğe kopyalamak anlamlı bir sürüm sınırını gizler. C compatible functions and enums

Hataları oluştuğu sınırda teşhis edin

İlk başarısız derleme adımını kullanarak araştırmayı daraltın. Bir başlık oluşturma hatası, C ayrıştırıcı hatası ve çözümlenmeyen sembol farklı düzeltmeler gerektirir.

İlk hata Sonraki kontrol
Swift @cyi reddeder Seçili Swift derleyici sürümünü yeniden kontrol edin; bu örnek Swift 6.3 veya üzeri gerektirir.
C Percent-Swift.h bulamaz Swift komutunun başarılı olduğunu ve her iki dosyanın da istenen dizinden derlendiğini onaylayın.
C demo_clamp_percent bulamaz Yeni oluşturulan başlığı inceleyin ve nitelik yazımını kontrol edin; kaynak değişikliklerden sonra yeniden derleyin.
C C++ veya Objective-C sözdizimi bildirir Hangi başlığın dahil edildiğini ve hangi araç zincirinin oluşturduğunu doğrulayın. Araştırma sırasında açık C derlemesini koruyun.
Bağlama dışa aktarılan işlevi çözümlüyemez Percent.o'nun son komutta dahil edildiğini ve güncel Swift kaynağından yeniden derlendiğini onaylayın.
Çalıştırılabilir beklenmedik sonuçlar bildiriyor Yazdırılan giriş/sonuç çiftini okuyun ve Swift dallarıyla karşılaştırın.

Bu sıra, Clang tarafından belgelenen derleyici aşamalarını takip eder: ayrıştırma kaynağın geçerli olup olmadığını belirler, nesne oluşturma derlenmiş kodu üretir ve bağlama derlenmiş girdileri birleştirir. Bu nedenle sadece başarılı bir C derlemesi, görevin yalnızca bir kısmını kanıtlar. Clang command guide

Örneği uyarlarken, C'ye bakan işlevi küçük tutun ve her yeni parametreye açık bir sözleşme verin. Metin için, kodlama ve uzunluk işlemeyi; arabellekler için, yazmadan önce kapasite ve sahipliğe karar verin. Bunlar bu tam-sayı-yüksekliği gösteriminin ötesindeki arayüz tasarımı kararlarıdır.

Bitmiş yerel kontrolün üç gözlemlenebilir sonucu vardır: oluşturulan başlık açık C derlemesi sırasında kabul edilir, her iki uygulama da tek bir çalıştırılabilir dosyaya bağlanır ve çağırıcı seçili girdileri doğrular. Bu kontrolleri, sentetik hesaplamayı kendi Swift işlevinizle değiştirirken koruyun.

Kaynaklar