共用方式為


在 Xamarin.iOS 中參考原生連結庫

Xamarin.iOS 支援使用原生 C 連結庫和 Objective-C 連結庫進行連結。 本文件討論如何將原生 C 連結庫與 Xamarin.iOS 項目連結。 如需針對 Objective-C 連結庫執行相同動作的詳細資訊,請參閱我們的 系結 Objective-C 類型 檔。

建置通用原生連結庫 (i386、ARMv7 和 ARM64)

通常建議針對 iOS 開發的每個支援平臺建置原生連結庫(適用於模擬器的 i386,以及裝置本身的 ARMv7/ARM64)。 如果您已經有連結庫的 Xcode 專案,這確實很簡單。

若要建置原生連結庫的 i386 版本,請從終端機執行下列命令:

/Developer/usr/bin/xcodebuild -project MyProject.xcodeproj -target MyLibrary -sdk iphonesimulator -arch i386 -configuration Release clean build

這會導致 下的 MyProject.xcodeproj/build/Release-iphonesimulator/原生靜態庫。 複製 (或移動) 連結庫封存盤案 (libMyLibrary.a) 到某個位置安全以供日後使用,為它提供唯一的名稱(例如 libMyLibrary-i386.a),使其不會與接下來要建置之相同連結庫的 arm64 和 armv7 版本發生衝突。

若要建置原生連結庫的 ARM64 版本,請執行下列命令:

/Developer/usr/bin/xcodebuild -project MyProject.xcodeproj -target MyLibrary -sdk iphoneos -arch arm64 -configuration Release clean build

這次建置的原生連結庫將會位於 MyProject.xcodeproj/build/Release-iphoneos/。 再次將這個檔案複製到安全的位置,將它重新命名為 libMyLibrary-arm64.a 之類的專案,使其不會發生衝突。

現在建置連結庫的 ARMv7 版本:

/Developer/usr/bin/xcodebuild -project MyProject.xcodeproj -target MyLibrary -sdk iphoneos -arch armv7 -configuration Release clean build

將產生的連結庫檔案複製到您移動其他 2 個連結庫版本的相同位置,將其重新命名為 libMyLibrary-armv7.a 之類的專案。

若要建立通用二進位檔,您可以使用 lipo 工具,如下所示:

lipo -create -output libMyLibrary.a libMyLibrary-i386.a libMyLibrary-arm64.a libMyLibrary-armv7.a

這會建立 libMyLibrary.a 一個通用 (fat) 連結庫,適合用於所有 iOS 開發目標。

遺漏必要的架構 i386

如果您在嘗試在 iOS 模擬器中取用連結庫時,在運行時間輸出中收到 does not implement methodSignatureForSelectordoes not implement doesNotRecognizeSelector 訊息,您的連結庫可能未針對 i386 架構進行編譯(請參閱上面的建置通用原生連結庫一節)。Objective-C

若要檢查指定連結庫支援的架構,請在終端機中使用下列命令:

lipo -info /full/path/to/libraryname.a

其中 /full/path/to/ 是所取用連結庫的完整路徑,而 libraryname.a 是有問題的連結庫名稱。

如果您有連結庫的來源,如果您想要在iOS模擬器上測試您的應用程式,則必須編譯並配套i386架構。

連結您的連結庫

您取用的任何第三方連結庫都必須以靜態方式連結您的應用程式。

如果您想要以靜態方式連結連結連結庫 “libMyLibrary.a”,您可以從因特網或使用 Xcode 建置,您需要執行一些動作:

  • 將連結庫帶入您的專案
  • 設定 Xamarin.iOS 連結連結庫
  • 從鏈接庫存取方法。

若要 將連結庫帶入您的專案,請從方案總管選取專案,然後按 Command+Option+a。 流覽至 libMyLibrary.a,並將它新增至專案。 出現提示時,請告訴 Visual Studio for Mac 或 Visual Studio 將它複製到專案中。 新增它之後,請在項目中尋找 libFoo.a,以滑鼠右鍵按兩下它,然後將 [建置動作] 設定[無]。

若要設定 Xamarin.iOS 以連結庫,請在最終可執行檔的項目選項上(不是連結庫本身,而是最終程式),您需要在 iOS 組建的額外自變數中新增 [-gcc_flags] 選項,後面接著包含程式所需的所有額外連結庫的引號字串, 例如:

-gcc_flags "-L$(MSBuildProjectDirectory) -lMylibrary -force_load $(MSBuildProjectDirectory)/libMyLibrary.a"

上述範例會連結 libMyLibrary.a

您可以使用 -gcc_flags 來指定任何命令行自變數集,以傳遞至用來執行可執行檔最終連結的 GCC 編譯程式。 例如,這個命令行也會參考 CFNetwork 架構:

-gcc_flags "-L$(MSBuildProjectDirectory) -lMylibrary -lSystemLibrary -framework CFNetwork -force_load $(MSBuildProjectDirectory)/libMyLibrary.a"

如果您的原生連結庫包含 C++ 程式代碼,您也必須在 「Extra Arguments」 中傳遞 -cxx 旗標,讓 Xamarin.iOS 知道使用正確的編譯程式。 針對 C++,先前的選項看起來會像這樣:

-cxx -gcc_flags "-L$(MSBuildProjectDirectory) -lMylibrary -lSystemLibrary -framework CFNetwork -force_load $(MSBuildProjectDirectory)/libMyLibrary.a"

從 C 存取 C 方法#

iOS 上提供兩種原生連結庫:

  • 屬於操作系統一部分的共享連結庫。

  • 您隨附於應用程式的靜態連結庫。

若要存取上述任一項中定義的方法,您可以使用 Mono的 P/Invoke 功能 ,其與您在 .NET 中使用的技術相同,大致如下:

  • 判斷您要叫用的 C 函式
  • 判斷其簽章
  • 判斷它所在的連結庫
  • 撰寫適當的 P/Invoke 宣告

當您使用 P/Invoke 時,必須指定您要連結的連結庫路徑。 使用 iOS 共用連結庫時,您可以硬式編碼路徑,也可以使用我們在 中 Constants定義的便利常數,這些常數應該涵蓋 iOS 共用連結庫。

例如,如果您想要從 Apple 的 UIKit 連結庫叫用 UIRectFrameUsingBlendMode 方法,並在 C 中具有此簽章:

void UIRectFrameUsingBlendMode (CGRect rect, CGBlendMode mode);

您的 P/Invoke 宣告看起來會像這樣:

[DllImport (Constants.UIKitLibrary,EntryPoint="UIRectFrameUsingBlendMode")]
public extern static void RectFrameUsingBlendMode (RectangleF rect, CGBlendMode blendMode);

Constants.UIKitLibrary 只是定義為 “/System/Library/Frameworks/UIKit.framework/UIKit”的常數,EntryPoint 可讓我們選擇性地指定外部名稱 (UIRectFramUsingBlendMode),同時在 C# 中公開不同名稱,也就是較短的 RectFrameUsingBlendMode。

存取 C Dylibs

如果您需要在 Xamarin.iOS 應用程式中取用 C Dylib,在呼叫 DllImport 屬性之前需要一些額外的設定。

例如,如果我們有 Animal.dylib 的方法 Animal_Version ,我們將在應用程式中呼叫,則必須先通知 Xamarin.iOS 連結庫的位置,然後再嘗試取用它。

若要這樣做,請編輯 Main.CS 檔案,使其看起來如下:

static void Main (string[] args)
{
    // Load Dylib
    MonoTouch.ObjCRuntime.Dlfcn.dlopen ("/full/path/to/Animal.dylib", 0);

    // Start application
    UIApplication.Main (args, null, "AppDelegate");
}

其中 /full/path/to/ 是取用 Dylib 的完整路徑。 有了此程式代碼,我們就可以連結至 Animal_Version 方法,如下所示:

[DllImport("Animal.dylib", EntryPoint="Animal_Version")]
public static extern double AnimalLibraryVersion();

靜態庫

由於您只能在 iOS 上使用靜態庫,因此沒有外部共用連結庫可連結,因此 DllImport 屬性中的 path 參數需要使用特殊名稱 __Internal (請注意名稱開頭的雙底線字元),而不是路徑名稱。

這會強制 DllImport 查閱您在目前程序中參考的方法符號,而不是嘗試從共用連結庫載入它。