如何在Mac上使用Swift调用C接口开发条形码应用

虽然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

软件下载

混合使用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().iBarcodeCount
var pBarcodeResult: pBarcodeResult = nil
var barcodeIndex = 1
 
// print barcode recognition results
for 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 memory
dbr_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

时间: 2024-10-05 05:57:00

如何在Mac上使用Swift调用C接口开发条形码应用的相关文章

如何在mac上安装composer(How to install composer on the Mac)

Change into a directory in your path like cd /usr/local/bin Get Composer curl -sS https://getcomposer.org/installer | php Make the phar executable chmod a+x composer.phar Change into a project directory cd /path/to/my/project Use Composer as you norm

【转】如何在Mac上卸载Java

如何在 Mac 上卸载 Java? 本文适用于: 平台: Macintosh OS X Java 版本: 7.0, 8.0 使用终端卸载 Oracle Java 注:要卸载 Java,必须具有管理员权限,并且必须以 root 用户身份或者使用 sudo 工具来执行删除命令. 按照下面所示,删除一个目录和一个文件(符号链接): 单击位于停靠栏中的 Finder 图标 单击实用程序文件夹 双击终端图标 在"终端"窗口中,复制和粘贴命令:sudo rm -fr /Library/Intern

如何在 Mac 上通过 Boot Camp 安装 Windows?

如何在 Mac 上通过 Boot Camp 安装 Windows? The following contents are chosen from the apple website, thanks for your visit~~ Good time! Boot Camp 可帮助您在 Mac 上安装 Microsoft Windows.安装后,请重新启动 Mac,以在 macOS 和 Windows 之间切换. 开始之前,确保您已备齐所有必需物品: 基于 Intel 的 Mac 包含 64 位

如何在Mac上的NTFS格式化驱动器 - 三个简单的步骤

在运行macOS或OS X的Mac和运行Windows的PC之间共享数据可能并不那么简单.默认情况下,Mac只能从Windows格式的外部硬盘读取文件,而不能写入文件.这可以防止您使用Mac保存,编辑,复制或删除驱动器上存储的任何内容.这背后的原因是什么?Mac(HFS +)使用的文件系统与Windows(NTFS)中使用的文件系统不同. 如何在Mac上读取NTFS文件 有一个真正简单的解决方案,但是:您的Mac只需要一个驱动程序.适用于Mac的Tuxera NTFS是一个完整的读写NTFS驱动

Jira - 如何在Mac上安装并配置Jira

Jira 是常用的项目管理工具,现在介绍一下如何在Mac 上安装并配置Jira 首先, 安装并配置JAVA开发环境. (如Java version "1.8.0_211") JAVA安装与配置: JMeter 性能测试 - Mac系统下如何配置JAVA开发环境 其次,安装并配置MySQL.如Server Version: 5.7.25 MySQL Community Server (GPL) 在https://dev.mysql.com/downloads/mysql/5.7.html

如何在Mac上播放和查看SWF文件

有时,某些Mac用户可能会遇到必须打开或访问的SWF文件.如果您有需要在Mac上查看,播放或打开的SWF文件,则可以使用各种免费工具来实现. SWF是Adobe Flash文件的文件格式,在使用Web动画,某些类型的Web视频,图形作品,交互以及其他类似Web内容时,您可能会在各种不同情况下遇到SWF文件,通常是与Web相关或设计工作. 本教程将向您展示如何在Mac上轻松查看和播放SWF文件,我们将介绍几种不同的方法,以便您使用最适合自己的方法. 如何使用VLC在Mac上查看和播放SWF文件 V

利用Mac的功能键|如何在Mac上使用F键

Mac键盘的顶部是一组按键,这些按键的特征是F后跟1-12数字.这些键称为Mac功能键,使您可以通过按几个键来更改某些设置并快速访问Mac功能. 如果您是Mac的所有者,是时候学习这些键各自可以做什么了. 为什么要使用Mac功能键? 如果您曾经使用过键盘快捷键,那么您就会知道它的快捷程度.多亏了快捷键,将您的手移到鼠标或触控板上并导航到您要执行的操作所需的时间得以缩短.功能键的工作方式完全相同,可节省您工作,上网或游戏时的时间. 一些应用程序允许您自定义功能键以适合您的首选项.您也可以通过重新映

如何在Mac上使用Siri

在您的iPhone上,要求Siri执行命令很简单.但是,如果在计算机上工作时附近没有iPhone,会发生什么情况?您也可以在Mac上使用Siri.快速简便,使其成为iMac或MacBook的完美伴侣. 本文中的说明适用于任何运行macOS Sierra或更高版本的Mac . 如何在Mac上启用Siri 首次购买新Mac时,系统会要求您在设置过程中启用Siri.但是,如果您跳过该步骤,则需要先启用Siri,然后才能使用它. 1.在Mac上,单击屏幕左上角的Apple图标. 2.在菜单中,选择系统偏

如何在Mac上识别和删除损坏的字体

字体看起来像无害的文件,而且大多数时候都是这样.但是,就像任何计算机文件一样,字体可能会损坏或损坏.发生这种情况时,它们可能会导致文档或应用程序出现问题.在Mac上使用“ 字体簿”来验证已安装的字体,以确保文件可以安全使用. 注:本文提供的信息适用于以下操作系统中的“字体簿”:macOS Catalina(10.15)到Mac OS X Panther(10.3). 如果字体无法正确显示或根本无法在文档中显示,则字体文件可能已损坏.如果文档无法打开,则可能是文档中使用的一种字体出现了问题.使用“