iT邦幫忙

2023 iThome 鐵人賽

DAY 26
0

我們先前有產生出讀取環控晶片的動態連結函庫,但是在Electron應用程式中並不能像Windows console application一樣直接引入使用。要在Electron應用程式使用外部動態連結函庫或應用程式的話可以用node-ffi-napiNode-API 或是Child Process這三種方式:

  • node-ffi-napi
    • 使用純JavaScript載入及使用動態連結函庫。
  • Node-API
    • 直接使用C++直接編寫Addon(插件),讓插件加載成Node.js可以用的模組。
  • Child Process
    • 可以呼叫一個子程序去運行外部的應用程式或指令。
      依照我們的使用情境,node-ffi-napi較為符合需求,因為我們先前有編寫了動態連結函庫,可以使用node-ffi-napi來連結動態連結函庫,讓Electron應用程式可以呼叫動態連結函庫中的函式。

node-ffi-napi

全名為Node.js Foreign Function Interface for N-API,使用純JavaScript載入及使用動態連結函庫,而不用任何C++程式碼。下面是官方教學中提到的一個簡單的範例:

	var ffi = require('ffi-napi');

	var libm = ffi.Library('libm', {
		'ceil': [ 'double', [ 'double' ] ]
	});
	libm.ceil(1.5); // 2
  • 首先使用ffi-api模組。
  • 接著使用ffi.Library連結libm這個函式庫。
  • 然後宣告變數libm連結了libm庫。並返回其中的ceil,向上取整數函式。
  • 最後直接呼叫libm.ceil就可以使用libm庫中的ceil函式。

ref

node-ffi-napi的核心為refref拓展了node內建的Buffer類別,並讓它們的行為更像指標,ref本身有支援以下常見的C類型:

  • void
  • int8
  • uint8
  • int16
  • uint16
  • int32
  • uint32
  • int64
  • uint64
  • float
  • double
  • Object
  • CString
  • bool
  • byte
  • char
  • uchar
  • short
  • ushort
  • int
  • uint
  • long
  • ulong
  • longlong
  • ulonglong
  • size_t

而其他較為複雜的類型如結構陣列,就需要使用ref-struct-napiref-array-napi,以下例子由官方文件所提供:

  • ref-struct-napi
    truct timeval {
    time_t       tv_sec;   /* seconds since Jan. 1, 1970 */
    suseconds_t  tv_usec;  /* and microseconds */
    ;
    ``
    `` javascript
    ar ref = require('ref-napi')
    ar StructType = require('ref-struct-napi')
    
    / define the time types
    ar time_t = ref.types.long
    ar suseconds_t = ref.types.long
    
    / define the "timeval" struct type
    ar timeval = StructType({
    v_sec: time_t,
    v_usec: suseconds_t
    )
    
    / now we can create instances of it
    ar tv = new timeval
    ``
    
    
  • ref-array-napi
    ar ref = require('ref-napi')
    ar ArrayType = require('ref-array-napi')
    
    / typedef
    ar int = ref.types.int
    
    / define the "int[]" type
    ar IntArray = ArrayType(int)
    
    / now we can create array instances; the constructor takes the same arguments
    / the native JS Array class
    
    ar a = new IntArray(5) // by length
    .length // 5
    [0] = 0
    [1] = 1
    [2] = -1
    [3] = 2
    [4] = -2
    
    ar b = new IntArray([1, 2, 3, 4, 5]) // with an existing Array
    .length // 5
    [0] // 1
    [1] // 2
    [2] // 3
    [3] // 4
    [4] // 5
    ``
    
    

Library

node-ffi-napi最主要的API為Library,用來連結指定的函式庫及其中所提供的函式,變數使用ffi.Library連結函式庫並返回了函式庫內函式的宣告,這個變數就可以呼叫函式庫內的函式做使用,下面是ffi.Library的使用方式:

ffi.Library(libraryFile, { functionSymbol: [ returnType, [ arg1Type, arg2Type, ... ], ... ]);
  • libraryFile
    • 要連結的函式庫檔案。
  • functionSymbol
    • 要呼叫的函式名稱。
  • returnType
    • 函式的回傳類型。
  • arg1Type, arg2Type, ...
    • 函式的參數。

今天簡單介紹了node-ffi-napi的基本概念及用法,其餘更詳細的內容可以參考node-ffi-napi官方教學ref完整API文件

參考內容

node-ffi-napi/node-ffi-napi: A foreign function interface (FFI) for Node.js, N-API style (github.com)
Node-API | Node.js v20.8.0 Documentation (nodejs.org)
Child process | Node.js v20.8.0 Documentation (nodejs.org)


上一篇
Day25 Electron應用程式-5
下一篇
Day27 Electron應用程式-7
系列文
Windows Driver + Electron 學習筆記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言