Dengan Swift 6.3 atau lebih baharu, tandakan fungsi global dengan @c, jana pengepala keserasiannya, kompilkan pemanggil sebagai C, dan pautkan dengan swiftc. Panduan ini membina program baris perintah Mac natif yang kecil untuk menunjukkan setiap sempadan.

Tugas pembaca adalah khusus: memanggil pengiraan Swift daripada fail .c biasa tanpa mengkompilkan fail itu sebagai Objective-C atau C++. Dokumentasi keluaran rasmi Swift mengenal pasti @c sebagai ciri saling kendali C yang disokong dan diperkenalkan dalam Swift 6.3. Semak pengkompil yang dipasang sebelum mengikuti panduan lama tentang atribut percubaan. Swift 6.3 Dikeluarkan

Apakah yang membolehkan fungsi Swift dipanggil daripada C?

Tiga perkara mesti sepadan: pengisytiharan yang dibaca oleh pengkompil C, konvensyen panggilan yang digunakan oleh pelaksanaan, dan fail objek yang dibekalkan kepada pemaut. Pengepala menangani perkara pertama; ia tidak dapat membekalkan pelaksanaan yang tiada atau mengubah ABI fungsi sedia ada.

Atribut @c memberikan fungsi global Swift konvensyen panggilan C dan mengehadkan tandatangannya kepada jenis yang boleh diwakili dalam C. Argumen atribut pilihan menetapkan nama C-nya. Swift mengeluarkan pengisytiharan yang sepadan dalam bahagian serasi C pada pengepala keserasian yang dijananya. Tingkah laku ini dinyatakan dalam cadangan Swift Evolution yang telah dilaksanakan. Fungsi dan enum serasi C

Untuk contoh ini, antara muka menerima dan memulangkan integer C. Pengiraan rekaan ini mengehadkan peratus paparan kepada julat inklusif dari sifar hingga 100. Tiada penimbal, hasil yang diperuntukkan, atau jangka hayat objek yang perlu diselaraskan. Ini memastikan binaan pertama tertumpu pada pengkompilasian dan pemautan.

Semak dahulu toolchain Mac

Anda memerlukan persekitaran pembangunan macOS dengan Clang, SDK macOS, dan Swift 6.3 atau lebih baharu. Apple menyediakan alat baris perintah bersama Xcode dan turut menawarkan pakej Command Line Tools yang berasingan. Jika anda sudah mempunyai Xcode, Apple menyatakan pemasangan alat yang berasingan tidak diperlukan. Memasang alat baris perintah

Jalankan semakan ini dalam Terminal:

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

Periksa versi pengkompil Swift itu sendiri. Pengkompil yang lebih lama tidak memperoleh ciri @c hanya kerana SDK yang lebih baharu dipasang. Jika terdapat beberapa versi Xcode, Apple mendokumenkan cara memilih versi aktif dalam Xcode > Settings > Locations > Command Line Tools, atau menetapkannya untuk sesi shell dengan DEVELOPER_DIR. Mengkonfigurasi tetapan alat baris perintah

Arahan di bawah menggunakan xcrun untuk memanggil alat pembangunan yang dipilih. Apple mendokumenkan peranan penemuan alat ini dalam rujukan binaan baris perintahnya. Soalan Lazim Membina daripada Baris Perintah dengan Xcode

Cipta direktori kerja kosong dan simpan kedua-dua fail sumber di bawah di dalamnya. Jalankan arahan binaan dari direktori itu. Ini ialah binaan natif untuk Mac setempat; ia tidak mencipta binari universal atau mengkonfigurasi platform lain.

Tulis pelaksanaan Swift dan pemanggil C

Tentukan fungsi Swift yang dieksport

Simpan fail sumber Swift lengkap ini sebagai Percent.swift:

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

Nama Swift ialah clampPercent; nama yang digunakan oleh C ialah demo_clamp_percent. CInt dipetakan kepada int dalam C. Menggunakan pasangan eksplisit ini mengelakkan andaian bahawa Swift Int bermaksud int dalam C: pemetaan yang didokumenkan untuk Swift Int ialah ptrdiff_t. Fungsi dan enum serasi C

Fungsi ini membandingkan nilai dan memulangkan sama ada input atau pemalar. Pengiraannya tidak menyebabkan limpahan aritmetik, termasuk untuk input di luar julat peratus. Awalan pada nama yang dieksport ialah contoh konvensyen untuk membezakan antara muka ini daripada fungsi lain dalam program yang lebih besar.

Panggilnya daripada program C lengkap

Simpan fail ini sebagai main.c. Binaan akan mencipta pengepala yang disertakan:

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

Ketiga-tiga input menguji had bawah, nilai yang tidak berubah, dan had atas. Program ini menyemak hasil secara jelas dan memulangkan status bukan sifar jika terdapat ketidakpadanan, supaya outputnya lebih berguna daripada demonstrasi yang sekadar mencetak nombor.

Jana pengepala, kompilkan C, dan pautkan program

Jalankan urutan ini dalam shell dari direktori yang mengandungi kedua-dua fail. Setiap langkah binaan menghentikan urutan jika gagal:

(
    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
)

Arahan pertama menghasilkan objek Swift dan pengepala keserasian. Pemacu Swift mentakrifkan -emit-object sebagai output fail objek dan -parse-as-library sebagai menghuraikan sumber pustaka dan bukannya skrip. Ini membiarkan fail C menyediakan titik masuk boleh laksana. Pilihan pemacu pengkompil Swift

Walaupun namanya berasal daripada sejarah, -emit-objc-header-path turut meminta bahagian C pada pengepala keserasian untuk pengisytiharan @c. Cadangan yang telah dilaksanakan secara jelas mengekalkan bendera ini untuk tujuan tersebut. Jangan gantikan pengepala yang dijana dengan prototaip yang anda anggap betul secara manual. Fungsi dan enum serasi C

Arahan kedua ialah semakan penting terhadap bahasa sumber. Clang mendokumenkan -x sebagai pilihan bahasa input dan -c sebagai penghasilan fail objek tanpa pemautan. Di sini, -x c -std=c11 menetapkan agar pemanggil dikompilkan sebagai C11 sambil membaca pengepala sebenar yang dijana. Panduan arahan Clang

Seruan pengkompil terakhir memautkan kedua-dua fail objek dengan menggunakan pemacu Swift. Panduan pengkompil Swift sendiri mengesyorkan agar swiftc diminta memautkan fail, bukannya memasang arahan pemautan peringkat lebih rendah secara manual. Menyahpepijat Pengkompil

Output yang dijangka, berdasarkan cabang dalam contoh, ialah:

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

Arahan ini disemak berdasarkan dokumentasi yang diperoleh tetapi tidak dijalankan di sini: persekitaran penyelidikan ialah Linux dan tidak mempunyai swiftc mahupun Clang. Output di atas ialah hasil yang dijangka, bukannya laporan ujian Mac.

Pilih antara muka yang sepadan dengan kod sedia ada

Untuk antara muka baharu yang kecil pada Swift 6.3 atau lebih baharu, pendekatan pengepala yang dijana di atas memastikan pengisytiharan terikat secara langsung pada pelaksanaan. Dokumentasi keluaran turut menyokong pendekatan kedua: @c @implementation melaksanakan fungsi yang sudah diisytiharkan dalam pengepala C yang diimport, dan Swift menyemak agar tandatangannya sepadan. Ini berguna apabila API C sedia ada perlu kekal sebagai kontrak antara muka. Swift 6.3 Dikeluarkan

Jika projek sekeliling sudah memanggil Swift melalui C++, pengikatan C++ yang dijana oleh Swift menawarkan pilihan lain. Fungsi Swift awam diwakili sebagai fungsi C++ sebaris dalam ruang nama modul. Pemanggil C memerlukan penyesuai berasingan yang dikompilkan sebagai C++, yang mendedahkan pengisytiharan kecil untuk C. Unit terjemahan C akan menyertakan pengepala C penyesuai itu. Mencampurkan Swift dan C++

Dalam penyesuai sedemikian, extern "C" menetapkan pemautan bahasa C pada pengisytiharan atau takrif C++. Ia tidak menukar kandungan pengepala C++ menjadi sintaks C. Draf kerja C++ mentakrifkan spesifikasi pemautan dan membezakan pemautan bahasa daripada pengisytiharan biasa. Draf kerja C++: Spesifikasi pemautan

Untuk tutorial ini, menaik taraf pengkompil lama kepada versi yang menyokong @c ialah laluan yang disokong secara langsung. Cadangan itu menerangkan @_cdecl sebagai pendahulu percubaannya; menyalin ejaan lama itu ke dalam contoh baharu akan mengaburkan perbezaan versi yang penting. Fungsi dan enum serasi C

Diagnosis kegagalan pada sempadan tempat ia berlaku

Gunakan langkah binaan pertama yang gagal untuk mengecilkan skop siasatan. Kegagalan menjana pengepala, ralat penghuraian C, dan simbol yang tidak dapat diselesaikan memerlukan pembetulan yang berbeza.

Kegagalan pertama Semakan seterusnya
Swift menolak @c Semak semula versi pengkompil Swift yang dipilih; contoh ini memerlukan Swift 6.3 atau lebih baharu.
C tidak dapat mencari Percent-Swift.h Pastikan arahan Swift berjaya dan kedua-dua fail dibina dari direktori yang dimaksudkan.
C tidak dapat mencari demo_clamp_percent Periksa pengepala yang baru dijana dan semak ejaan atribut; bina semula selepas perubahan sumber.
C melaporkan sintaks C++ atau Objective-C Sahkan pengepala yang disertakan dan toolchain yang menjana pengepala itu. Kekalkan pengkompilasian C yang eksplisit semasa menyiasat.
Pemautan tidak dapat menyelesaikan fungsi yang dieksport Pastikan Percent.o disertakan dalam arahan terakhir dan dibina semula daripada sumber Swift semasa.
Program boleh laksana melaporkan hasil yang tidak dijangka Baca pasangan input/hasil yang dicetak dan bandingkannya dengan cabang Swift.

Urutan ini mengikuti peringkat pengkompil yang didokumenkan oleh Clang: penghuraian menentukan sama ada sumber itu sah, penjanaan objek menghasilkan kod terkompil, dan pemautan menggabungkan input yang telah dikompilkan. Oleh itu, pengkompilasian C yang berjaya sahaja hanya memenuhi sebahagian daripada tugas. Panduan arahan Clang

Apabila mengubah suai contoh ini, pastikan fungsi yang menghadap C ringkas dan tetapkan kontrak yang jelas untuk setiap parameter baharu. Untuk teks, tentukan pengekodan dan cara pengendalian panjang; untuk penimbal, tentukan kapasiti dan pemilikan sebelum menulis pembalut. Itu ialah keputusan reka bentuk antara muka yang melangkaui demonstrasi integer sahaja ini.

Semakan setempat yang lengkap mempunyai tiga hasil yang boleh diperhatikan: pengepala yang dijana diterima semasa pengkompilasian C secara eksplisit, kedua-dua pelaksanaan dipautkan menjadi satu program boleh laksana, dan pemanggil mengesahkan input yang dipilih. Kekalkan semakan ini apabila menggantikan pengiraan rekaan dengan fungsi Swift anda sendiri.

Sumber