如何在Mac上使用Swift調用C介面開發條碼應用

來源:互聯網
上載者:User

標籤:

雖然Objective-C還活的很好,但是蘋果已經把重心轉移到Swift上。未來Mac和iOS的開發必然是以Swift為主。因為Swift還比較新,很多SDK還沒有提供Swift版本。這裡分享下如何使用Swift來調用C。

參考原文:How to Bridge C Code to Create Swift Barcode Reader on Mac

Xiao Ling

翻譯:yushulx

軟體下載
  • Dynamsoft Barcode SDK for Mac

  • Xcode 6.4

混合使用Swift和C

蘋果在iBooks裡提供了電子書Using Swift with Cocoa and Objective-C。在網頁上可以閱讀Interacting with C APIs。

Swift和C類型映射關係參考:

使用Swift和C在Mac上實現1D/2D條碼應用

在Xcode中使用快速鍵Command+Shift+N建立新工程。

標頭檔和依賴的庫直接拖入工程就行了。Xcode會自動關聯。

Command+N建立一個C檔案,用於調用底層的C動態連結程式庫(Dynamsoft Barcode dylib)。

完成之後,Xcode會彈出提示:

確認之後,Xcode會自動產生一個橋接標頭檔。把C用到的標頭檔添加進去:

#import "native_lib.h"

參考Dynamsoft Barcode SDK的線上程式碼範例做一些修改:

#include "native_lib.h" int dbr_release_memory(pBarcodeResultArray paryResult){    DBR_FreeBarcodeResults(&paryResult);    printf("Game Over\n");    return 0;} pBarcodeResultArray dbr_decodeBarcodeFile(char* pszImageFile){    // Parse command    __int64 llFormat = (OneD |QR_CODE);     int iMaxCount = 0x7FFFFFFF;    int iIndex = 0;    ReaderOptions ro = {0};    pBarcodeResultArray paryResult = NULL;    int iRet = -1;    char * pszTemp = NULL;    char * pszTemp1 = NULL;    struct timeval begin, end;     if (NULL == pszImageFile)    {        printf("The syntax of the command is incorrect.\n");        return NULL;    }     // Set license    DBR_InitLicense("A825E753D10C6CAC7C661140EC5ABEC3");     // Read barcode    gettimeofday(&begin, NULL);    ro.llBarcodeFormat = llFormat;    ro.iMaxBarcodesNumPerPage = iMaxCount;    iRet = DBR_DecodeFile(pszImageFile, &ro, &paryResult);    gettimeofday(&end, NULL);     // Output barcode result    pszTemp = (char*)malloc(4096);    if (iRet != DBR_OK)    {        sprintf(pszTemp, "Failed to read barcode: %s\r\n", DBR_GetErrorString(iRet));        printf("%s", pszTemp);        free(pszTemp);        return NULL;    }     if (paryResult->iBarcodeCount == 0)    {        sprintf(pszTemp, "No barcode found. Total time spent: %.3f seconds.\r\n",                ((float)((end.tv_sec * 1000 * 1000 +  end.tv_usec) - (begin.tv_sec * 1000 * 1000 + begin.tv_usec))/(1000 * 1000)));        printf("%s", pszTemp);        DBR_FreeBarcodeResults(&paryResult);        return 0;    }     sprintf(pszTemp, "Total barcode(s) found: %d. Total time spent: %.3f seconds\r\n\r\n", paryResult->iBarcodeCount,            ((float)((end.tv_sec * 1000 * 1000 +  end.tv_usec) - (begin.tv_sec * 1000 * 1000 + begin.tv_usec))/(1000 * 1000)));    printf("%s", pszTemp);     return paryResult;}

修改下產生的標頭檔:

#ifndef __DBRConsole__native_lib__#define __DBRConsole__native_lib__ #include <stdio.h> #include <stdlib.h>#include <string.h>#include <sys/time.h> #include "If_DBR.h" pBarcodeResultArray dbr_decodeBarcodeFile(char* fileName);int dbr_release_memory(pBarcodeResultArray paryResult);const char * GetFormatStr(__int64 format); #endif /* defined(__DBRConsole__native_lib__) */
用Swift編寫命令列工具

把Swift中的String轉換成char *:

var file: String = "/Applications/Dynamsoft/Barcode Reader 3.0 Trial/Images/AllSupportedBarcodeTypes.tif" // barcode file//let namePtr = strdup(filePath.bridgeToObjectiveC().UTF8String) var filePtr = strdup(file.cStringUsingEncoding(NSUTF8StringEncoding)!)var fileName: UnsafeMutablePointer<CChar> = UnsafeMutablePointer(filePtr)

注釋掉的介面bridgeToObjectiveC 在早期的Swift版本中是可以用的。Xcode 6.4中已經去掉了。

命令列擷取Barcode結果:

var result : pBarcodeResultArray = dbr_decodeBarcodeFile(fileName) free(filePtr) println("Total barcode: \(String(result.move().iBarcodeCount))\n.......") var count = result.move().iBarcodeCountvar pBarcodeResult: pBarcodeResult = nilvar barcodeIndex = 1 // print barcode recognition resultsfor i in 0..<Int(count) {    pBarcodeResult = result.move().ppBarcodes.advancedBy(i).move()    println("Barcode: \(barcodeIndex++)")    println("Page: \(String(pBarcodeResult.move().iPageNum))")    var lFormat: __int64 = pBarcodeResult.move().llFormat    var format = String.fromCString(GetFormatStr(lFormat))    println("Type: \(format!)")    println("Value: \(String.fromCString(pBarcodeResult.move().pBarcodeData)!)")    println(".......") } // free C memorydbr_release_memory(result)

用Swift建立Cocoa應用

AppDelegate.swift中建立按鈕和文本控制項:

@IBOutlet weak var window: NSWindow!@IBOutlet weak var btLoad: NSButton!@IBOutlet weak var btRead: NSButton!@IBOutlet weak var text: NSTextField!@IBOutlet weak var filePath: NSTextField!

建立按鈕響應函數:

@IBAction func onClick(sender: NSButton) {        var title = sender.title        switch(title) {        case "Load Barcode File":            dispatch_async(dispatch_get_main_queue()) {                self.openPanel()            }            break        case "Read Barcode":             if self.filePath.stringValue == "" {                text.stringValue = "Please add image path!"                return            }             println("default:" + self.filePath.stringValue)            var dbr = DBR()            text.stringValue = dbr.decodeFile(self.filePath.stringValue)!            break        default:            break        }     }

在Interface Builder中把代碼和UI元素關聯起來:

使用NSOpenPanel 負載檔案:

func openPanel() {        var openPanel = NSOpenPanel()        openPanel.allowsMultipleSelection = false        openPanel.canChooseDirectories = false        openPanel.canCreateDirectories = false        openPanel.canChooseFiles = true        openPanel.beginWithCompletionHandler { (result) -> Void in            if result == NSFileHandlingPanelOKButton {                if let path = openPanel.URL?.path {                    self.filePath.stringValue = path                }            }        }     }

建立DBR.swift用於讀取條碼:

import Foundation class DBR {    func decodeFile(file: String)->String? {         var filePtr = strdup(file.cStringUsingEncoding(NSUTF8StringEncoding)!)        var fileName: UnsafeMutablePointer<CChar> = UnsafeMutablePointer(filePtr)        var result : pBarcodeResultArray = dbr_decodeBarcodeFile(fileName)         free(filePtr)         println("Total barcode: \(String(result.move().iBarcodeCount))\n.......")         var count = result.move().iBarcodeCount        var barcodeIndex = 1        var results: String = ""        // print barcode recognition results        for i in 0..<Int(count) {            var pBarcodeResult = result.move().ppBarcodes.advancedBy(i).move()             results += "Barcode: \(barcodeIndex++)\n"            results += "Page: \(String(pBarcodeResult.move().iPageNum))\n"             var lFormat: __int64 = pBarcodeResult.move().llFormat            var format = String.fromCString(GetFormatStr(lFormat))             results += "Type: \(format!)\n"            results += "Value: \(String.fromCString(pBarcodeResult.move().pBarcodeData)!)\n"            results += ".......\n"         }         // free C memory        dbr_release_memory(result)         return results    }}

運行1D/2D條碼應用:

源碼

https://github.com/yushulx/swift-barcode-reader


如何在Mac上使用Swift調用C介面開發條碼應用

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.