如何在Mac上用Ruby封装C/C++接口

来源:互联网 时间:1970-01-01


最近在codecademy上学习了下Ruby,顺便分享下如何在Mac上用Ruby封装Dynamsoft C/C++ barcode API 。

参考原文:How to Make Ruby Barcode Reader with C++ Barcode SDK on Mac OS X

作者:Xiao Ling

翻译:yushulx

下载SDK

http://www.dynamsoft.com/Downloads/Dynamic-Barcode-Reader-Download.aspx

创建Ruby Barcode工程

创建extconf.rb:

?1234567require 'mkmf'  extension_name = 'dynamsoftbarcode'  dir_config(extension_name)  create_makefile(extension_name)

自动生成Makefile:

?1ruby extconf .rb

打开Makefile,修改配置。

  • 添加头文件路径

    ?123dbrdir = /Applications/Dynamsoft/Barcode/ Reader/ 3.0/ Trial/Include  INCFLAGS = -I. -I$(arch_hdrdir) -I$(hdrdir)/ruby/backward -I$(hdrdir) -I$(srcdir) -I$(dbrdir)
  • 添加库路径

    ?1LIBS = $(LIBRUBYARG_SHARED) -lpthread -ldl -lobjc -lDynamsoftBarcodeReader

打开dynamsoftbarcode.c,添加入口和方法:

?12345678910111213141516VALUE BarcodeReader = Qnil;  void Init_dynamsoftbarcode();  VALUE method_decodeFile(VALUE selfVALUE path);  void Init_dynamsoftbarcode() {    BarcodeReader = rb_define_module("BarcodeReader");    rb_define_method(BarcodeReader, "decodeFile", method_decodeFile, 1);}  VALUE method_decodeFile(VALUE selfVALUE path) {    char *pszPath = StringValueCStr(path);    VALUE ary = decode(pszPath);    return ary;}

使用Dynamsoft Barcode SDK提供的代码:

?123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/time.h>#include <If_DBR.h>  #define strcmpi(dst, src) strcasecmp(dst, src)  __int64 GetFormat(const char * pstr){    __int64 llFormat = 0;    const char * pszFormat = pstr;      if (strcasestr(pszFormat, "code_39") != NULL)        llFormat |= CODE_39;    if (strcasestr(pszFormat, "code_128") != NULL)        llFormat |= CODE_128;    if (strcasestr(pszFormat, "code_93") != NULL)        llFormat |= CODE_93;    if (strcasestr(pszFormat, "codabar") != NULL)        llFormat |= CODABAR;    if (strcasestr(pszFormat, "itf") != NULL)        llFormat |= ITF;    if (strcasestr(pszFormat, "upc_a") != NULL)        llFormat |= UPC_A;    if (strcasestr(pszFormat, "upc_e") != NULL)        llFormat |= UPC_E;    if (strcasestr(pszFormat, "ean_13") != NULL)        llFormat |= EAN_13;    if (strcasestr(pszFormat, "ean_8") != NULL)        llFormat |= EAN_8;    if (strcasestr(pszFormat, "industrial_25") != NULL)        llFormat |= INDUSTRIAL_25;    if (strcasestr(pszFormat, "oned") != NULL)        llFormat = OneD;    if (strcasestr(pszFormat, "qr_code") != NULL)        llFormat |= QR_CODE;      return llFormat;}  const char * GetFormatStr(__int64 format){    if (format == CODE_39)        return "CODE_39";    if (format == CODE_128)        return "CODE_128";    if (format == CODE_93)        return "CODE_93";    if (format == CODABAR)        return "CODABAR";    if (format == ITF)        return "ITF";    if (format == UPC_A)        return "UPC_A";    if (format == UPC_E)        return "UPC_E";    if (format == EAN_13)        return "EAN_13";    if (format == EAN_8)        return "EAN_8";    if (format == INDUSTRIAL_25)        return "INDUSTRIAL_25";    if (format == QR_CODE)        return "QR_CODE";      return "UNKNOWN";}  int decode(const char *pszImageFile){    __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 beginend;      if (NULL == pszImageFile)    {        printf("The syntax of the command is incorrect./n");        return 1;    }      // Set license    DBR_InitLicense("B8DF4560D0953299D5454C71A38D1FEB");      // Read barcode    gettimeofday(&beginNULL);    ro.llBarcodeFormat = llFormat;    ro.iMaxBarcodesNumPerPage = iMaxCount;    iRet = DBR_DecodeFile(pszImageFile, &ro, &paryResult);    gettimeofday(&endNULL);      // 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 1;    }      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);    for (iIndex = 0; iIndex < paryResult->iBarcodeCount; iIndex++)    {        sprintf(pszTemp, "Barcode %d:/r/n", iIndex + 1);        // printf("%s", pszTemp);        sprintf(pszTemp, "%s    Page: %d/r/n", pszTemp, paryResult->ppBarcodes[iIndex]->iPageNum);        // printf("%s", pszTemp);        sprintf(pszTemp, "%s    Type: %s/r/n", pszTemp, GetFormatStr(paryResult->ppBarcodes[iIndex]->llFormat));        // printf("%s", pszTemp);        pszTemp1 = (char*)malloc(paryResult->ppBarcodes[iIndex]->iBarcodeDataLength + 1);        memset(pszTemp1, 0, paryResult->ppBarcodes[iIndex]->iBarcodeDataLength + 1);        memcpy(pszTemp1, paryResult->ppBarcodes[iIndex]->pBarcodeData, paryResult->ppBarcodes[iIndex]->iBarcodeDataLength);        sprintf(pszTemp, "%s    Value: %s/r/n", pszTemp, pszTemp1);        // printf("%s", pszTemp);        free(pszTemp1);    }      free(pszTemp);    DBR_FreeBarcodeResults(&paryResult);      return iRet;}

把C String转换成 VALUE(VALUE表示Ruby对象)。

?12VALUE ary = rb_ary_new();rb_ary_push(ary, rb_str_new_cstr(pszTemp));

创建Ruby脚本barcode_reader.rb调用接口:

?1234567891011121314require 'dynamsoftbarcode'include BarcodeReader  if ARGV.length == 0  puts "Please add a barcode file path!"else  $filePath ARGV[0]  $results = decodeFile($filePath)  $results.each do |i|     puts "#{i}"  end    puts "Game Over!"end

执行make。如果看到下面的警告:

?1ld: warning: directory not found for option '-L/usr/local/lib'

打开Makefile ,把

?1ldflags = -L. -L/usr/local/lib

改成

?1ldflags = -L. -L/usr/lib.

再make一次就好了:

?1linking shared-object dynamsoftbarcode.bundle

运行sudo make install安装。

执行脚本测试:

?1ruby barcode_reader.rb barcode_file

截图:

参考

  • http://docs.ruby-lang.org/en/2.1.0/README_EXT.html

  • https://silverhammermba.github.io/emberb/c/

源码

https://github.com/dynamsoftsamples/ruby-barcode-reader




相关阅读:
Top