如何在Swift中調用C庫(完結篇)

jopen 8年前發布 | 8K 次閱讀 Linux Apple Swift開發

上篇如何在 Swift中調用C庫(進階篇) 中,我們已經解決了大部分的問題,本篇我們來講講如何完善這個示例。

之前我們的示例中包含了以下幾個項目:

  • hiredis-bridge 用于橋接兼容hiredis庫中的一些方法。
  • CHiredis 用于映射hiredis和hiredis-bridge中的方法到Swift中去。
  • SwiftHiredis 通過CHiredis來調用hiredis和hiredis-bridge中的方法。

這些項目都是運行在Linux平臺下,我們來看看如何將這個示例兼容Mac平臺。

在Mac上安裝Reids和Hiredis

使用Homebrew來安裝:

brew install redis hiredis

然后使用下面命令運行redis:

redis-server /usr/local/etc/redis.conf

修改hiredis-bridge

主要是要修改hiredis-bridge的Makefile

TARGET = hiredis_bridge
LIB_NAME = hiredis_bridge

PREFIX ?= /usr/local

UNAME := $(shell uname)

all: $(TARGET)

$(TARGET): *.c
ifeq ($(UNAME), Linux) # build for linux
    clang -c *.c
    ar -rcs lib$(LIB_NAME).a *.o
endif
ifeq ($(UNAME), Darwin) # build for darwin
    clang -c *.c -I$(PREFIX)/include
    clang -dynamiclib *.o -I$(PREFIX)/include $(PREFIX)/lib/libhiredis.dylib -o lib$(LIB_NAME).dylib
endif
    rm *.o

install:
    mkdir -p $(TARGET)/usr/local/lib
    mkdir -p $(TARGET)/usr/local/include/$(TARGET)
    cp *.h $(TARGET)/usr/local/include/$(TARGET)
ifeq ($(UNAME), Linux)
    # copy .a
    cp lib$(LIB_NAME).a $(TARGET)/usr/local/lib/
    rm lib$(LIB_NAME).a
endif
ifeq ($(UNAME), Darwin)
    # copy .dylib
    cp lib$(LIB_NAME).dylib $(TARGET)/usr/local/lib/
    rm lib$(LIB_NAME).dylib
endif
    mkdir -p $(PREFIX)
    cp -r $(TARGET)/usr/local/* $(PREFIX)/
    rm -r $(TARGET)

Makefile主要作用是編譯,然后把hiredis-bridge的頭文件和庫文件放到對應的位置上去。不過因為Linux和Mac環境的區別,編譯的方法會不一樣。Linux編譯出來是靜態庫,后綴為.a;Mac需要編譯出動態庫,后綴為.dylib。然后都會把頭文件(.h)放到/usr/local/include/目錄下,庫文件(.a或.dylib)放到/usr/local/lib/目錄下。

代碼更新到github上: https://github.com/fengluo/hiredis-bridge/tree/c3a7f568bde781a37ebd29584a6357129284d1f6 tag: 0.2.0

創建CHiredis-OSX

hiredis在Linux和Mac下的安裝位置不一樣。Linux下,hiredis的頭文件位置在/usr/include/,而Mac下則位于/usr/local/include/。SPM(Swift Package Manager)在 文檔 中有提到過這個問題,并聲稱會在將來解決。我們現在的解決方法則是創建一個新的映射庫。

只要把之前的 CHiredis 復制過來,修改module.modulemap中的header路徑即可:

module CHiredis [system] {
    header "/usr/local/include/hiredis/hiredis.h"
    header "/usr/local/include/hiredis_bridge/hiredis-bridge.h"
    link "hiredis"
    link "hiredis_bridge"
    export *
}

并且需要在Package.swift中定義包的名稱,否則編譯后這個包會以CHiredis-OSX為名出現。

import PackageDescription

let package = Package(
  name: "CHiredis"
)

代碼上傳到github上: https://github.com/fengluo/CHiredis-OSX tag: 0.2.0

修改SwiftHiredis

在SwiftHiredis,我們需要基于現在的系統平臺來選擇依賴的映射庫:CHiredis or CHiredis-OSX。只要簡單的改動即可:

import PackageDescription

#if os(OSX)
    let CHiredisURL = "https://github.com/fengluo/CHiredis-OSX.git"
#else
    let CHiredisURL = "https://github.com/fengluo/CHiredis.git"
#endif

let package = Package(
    dependencies: [
        .Package(url: CHiredisURL, majorVersion: 0, minor: 2)]
)

這樣對于該示例的跨平臺兼容就解決了。在SwiftHiredis編譯運行測試一下:

swift build
.build/debug/SwiftHiredis

就會得到上篇文章一樣的結果 1234 。

代碼更新到github上: https://github.com/fengluo/SwiftHiredis/tree/b1927cc9680103e51c9d114a18427d49c26d461f tag: 0.3.0

總結

至此,『如何在Swift中調用C庫』這個系列我就寫完了,基本上都是經驗之談。以后會繼續講解Swift在服務端的開發。

Enjoy it!

來自: http://hearrain.com/2016/01/855

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!