
في عام 2014 ، تم تقديم Swift ، وهي لغة جديدة لتطوير تطبيقات النظام البيئي من Apple. جلبت الجدة ليس فقط ميزات ووظائف جديدة ، ولكن أيضًا مشاكل - لأولئك الذين أرادوا استخدام مكتبات C القديمة الجيدة. في هذه المقالة ، سأناقش واحدًا منها - تجميع مكتبة C في إطار Swift. هناك عدة طرق لحلها ؛ في هذه الحالة ، سأشرح كيفية القيام بذلك باستخدام وحدات clang الصريحة.
على سبيل المثال ، نأخذ مكتبة
libgif C الخارجية
ونضمّنها في إطار Swift GifSwift الخاص بنا. إذا كنت تريد رؤية النتيجة على الفور ، فيمكنك مشاهدة المشروع بالكامل
هنا .
إعداد libgif
قبل تضمين مكتبة libgif في مشروعنا ، تحتاج إلى تجميعها من المصدر.
- قم بتنزيل أحدث لعبة tarball هنا .
- فك حزمة الأرشيف ، باستخدام وحدة التحكم ، انتقل إلى المجلد وتشغيله:
./configure && make check
ملاحظة: من أجل البساطة ، نقوم بتجميع مكتبة لنظام التشغيل x86-64 ، وبالتالي ستعمل فقط في محاكي iOS أو على نظام ماك. يعد إنشاء مكتبة ثابتة متعددة الهندسة موضوعًا منفصلًا ، لا أتطرق إليه في هذه المقالة. يمكن العثور على تعليمات مفيدة هنا .
- إذا
${lib_gif_source}/lib/.libs
بدون أخطاء ، فيمكنك العثور على ملفات المكتبة في ${lib_gif_source}/lib/.libs
. نحن مهتمون بملفين:
lib/.libs/libgif.a # lib/gif_lib.h #
إعداد المشروع
الآن سنقوم بتخصيص المشروع حسب احتياجاتنا.
- أنشئ مشروعًا جديدًا باستخدام قالب Cocoa Touch Framework ، واسمه GifSwift .
- أضف ملفات مكتبة libgif التي أنشأناها إلى مجموعة منفصلة داخل المشروع.
- أضف هدفًا جديدًا لتطبيق الاختبار إلى المشروع لمشاهدة النتيجة.
يجب أن يبدو الهيكل النهائي للمشروع كما يلي:

استيراد إلى سويفت
لاستيراد مكتبة C إلى Swift ، يجب أن نصفها كوحدة
نمطية . الوصف هو ملف
.modulemap يحتوي على قائمة بملفات الرأس للاستيراد والمكتبات الثابتة للربط. يمكن استيراد الوحدة النمطية الناتجة إلى رمز Swift أو Objective-C (باستخدام
@import
).
ستعمل هذه الطريقة لاستيراد المكتبة إلى الإطار في معظم الحالات (اقرأ المزيد حول هذا النهج
هنا ). يعمل بشكل رائع إذا كنت تقوم بإنشاء إطار داخلي أو مجرد تقسيم التطبيق الخاص بك إلى وحدات. ولكن هذه الطريقة لديها أيضا عيوب. على سبيل المثال ، يكون غير فعال إذا كنت تريد نقل مكتبتك إلى شخص يستخدم قرطاج أو Cocoapods أو بسبب قطعة أثرية ثنائية. والسبب في ذلك هو أن الإطار الناتج غير محمول بشكل عام ، لأنه عند تجميعه يرتبط بموقع محدد لملفات الرأس والمكتبات من خريطة الوحدة النمطية على جهاز الكمبيوتر الخاص بك.
وحدة صريحة
للتغلب على هذه القيود ، سوف نستخدم طريقة أخرى - الوحدة النمطية
الصريحة للمكتبة. الوحدة النمطية الصريحة عبارة عن وحدة نمطية يتم الإعلان عنها كوحدة فرعية باستخدام الكلمة الأساسية
الصريحة ، ويتم وضعها في الوحدة النمطية الأصل ،
ولا يتم
استيرادها تلقائيًا. يعمل بشكل مشابه لـ
*_Private.h
عمل الهدف- C. إذا كنت تريد استخدام واجهة برمجة التطبيقات المعلنة فيها ، فيجب عليك استيراد الوحدة النمطية
بشكل صريح (صراحة).نحن بصدد إنشاء وحدة نمطية واضحة لمكتبة C داخل الإطار. للقيام بذلك ، نحتاج إلى إعادة تعريف وحدة Xcode التي تم إنشاؤها. لاحظ أيضًا أننا لا نحدد مكتبة libgif.a للرابط (link gif) ، ولكن بدلاً من ذلك نقوم بذلك مباشرة في المشروع باستخدام واجهة Xcode.
ملاحظة: لمعرفة المزيد حول الوحدات النمطية الصريحة ، انقر هنا.- أضف ملفًا يسمى GifSwift.modulemap إلى مجلد جذر المشروع:
framework module GifSwift { umbrella header "GifSwift.h" explicit module CLibgif { private header "gif_lib.h" } export * }
يحتوي هذا الملف على مواصفات الوحدة النمطية CLibgif الصريحة ويتألف من ملف رأس واحد مُعلن (حيث يوجد ملف واحد فقط في مكتبتنا). يتم تحميل الملف في الوحدة النمطية الناتجة للإطار.
- لا يلزم إضافة ملف وصف الوحدة النمطية إلى الإطار ، ولكن يجب تحديده في الإعدادات الهدف:
Build Settings — Packaging — Module Map (MODULEMAP_FILE) = $SRCROOT/GifSwift/GifSwift.modulemap
- يجب إضافة ملفات libgif إلى هدف الإطار باعتباره رأسًا خاصًا ( gif_lib.h ) ومكتبة ثابتة ( libgif.a ). يرجى ملاحظة أنه تمت إضافة ملف الرأس لمكتبة C إلى الهدف كملف خاص. هذا ضروري لوحدة لدينا واضحة. لا شيء يمنع إضافة ملف الرأس هذا بشكل عام ، لكن مهمتنا هي إخفاء تفاصيل التنفيذ بأقصى قدر ممكن.

- يمكنك الآن استيراد الوحدة النمطية الصريحة داخل الإطار باستخدام
import GifSwift.CLibgif
غلاف سريع
الآن يمكنك أن تفعل واجهة إطارنا. فئة واحدة كافية ، وهو gif مع اثنين من الخصائص:
import Foundation import GifSwift.CLibgif public class GifFile { private let path: URL private let fileHandlePtr: UnsafeMutablePointer<GifFileType> private var fileHandle: GifFileType { return self.fileHandlePtr.pointee } deinit { DGifCloseFile(self.fileHandlePtr, nil) } // MARK: - API public init?(path: URL) { self.path = path let errorCode = UnsafeMutablePointer<Int32>.allocate(capacity: 1) if let handle = path.path.withCString({ DGifOpenFileName($0, errorCode) }) { self.fileHandlePtr = handle DGifSlurp(handle) } else { debugPrint("Error opening file \(errorCode.pointee)") return nil } } public var size: CGSize { return CGSize(width: Double(fileHandle.SWidth), height: Double(fileHandle.SHeight)) } public var imagesCount: Int { return Int(fileHandle.ImageCount) } }
يلتف
GifFile.swift
برمجة منخفضة المستوى لمعالجة الملفات والوصول إلى بعض الخصائص ، ورسم خرائط لها على أنواع Foundation أكثر ملاءمة.
تحقق
من أجل اختبار مكتبتنا ، أضفت ملف
cat.gif إلى المشروع:
import UIKit import GifSwift class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() if let file = GifFile(path: Bundle.main.url(forResource: "cat", withExtension: "gif")!) { debugPrint("Image has size: \(file.size) and contains \(file.imagesCount) images") } } }
عند تشغيل هذا الرمز في وحدة التحكم ، سنرى ما يلي:
" حجم الصورة: (250.0 ، 208.0) وتحتوي على 44 صورة"
الاستنتاجات
يحتوي إطار العمل الناتج على كل ما تحتاج إلى استخدامه ، ويحتوي على واجهة Swift ، ويخفي رمز C من العملاء افتراضيًا. ومع ذلك ، هذا ليس صحيحا تماما. كما كتبت أعلاه ،
يتيح لك استيراد
GifSwift.CLibgif الوصول إلى جميع الوحدات الخاصة ، ومع ذلك ، فإن طريقة التغليف هذه افتراضيًا كافية لإخفاء تفاصيل تطبيق الإطار.