成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

技術干貨 | Electron 插件開發實踐

開發
Electron 是以 Nodejs 和 Chromiu m 為內核的跨平臺開發框架。 本文結合網易云信的實踐經驗,對 js 和 C++ 混合編程在 Electron 桌面程序中的應用進行介紹。

01 前言

早期跨平臺桌面應用開發大多采用 Qt 和 C++,受語言學習成本開發效率影響,越來越多的人將目光轉向了 Electron。Electron 是以 Nodejs 和 Chromium 為內核的跨平臺開發框架。

Electron 基于 Web 技術開發桌面應用,Web 技術在軟件開發領域應用非常廣泛,生態較為成熟,學習成本較低、開發效率高。但是 Web 在處理多線程、并發場景時顯得捉襟見肘,Electron 底層有 Nodejs 支持,Nodejs 的插件模塊具有調用 C++ 的能力,C++ 非常適合處理高并發、音視頻等復雜業務,彌補了 Web 的性能問題。本文就 js 和 C++ 混合編程在 Electron 桌面程序中的應用進行介紹。

Nodejs 中使用 C++,有以下幾種方式:

  • 將 C++ 程序作為獨立子進程使用。
  • 通過 node-ffi 方式調用。
  • Nodejs 擴展,將 C++ 代碼編譯為 Nodejs 模塊,本文主要針對這種方式進行介紹。

02 C++ 擴展

C++ 擴展簡介 

Nodejs 本身采用 C++ 編寫,所以我們可以使用 C++ 編寫的自己的 Nodejs 模塊,可以像 Nodejs 原生模塊一樣使用。C++ 擴展格式為 .node,其本質為動態鏈接庫,相當于 Windows 下 .dll。C++ 擴展作為動態鏈接庫,通過 dlopen 在 Nodejs 中加載。

C++ 擴展架構圖:

C++ 擴展實現的幾種方式 

實現 C++  擴展有3種方式:原生模式、nan、Node-API。

  • 原生模式直接使用 Nodejs API 及 Chrome V8 API 進行開發,這種方式早已被遺棄。特點: Nodejs API 和 Chrome V8 API 接口一旦變化,依賴這些 API 的 C++ 擴展便無法使用,特定版本的 C++ 擴展只能在對應版本 Nodejs 環境中使用。
  • nan(N ative Abstractions for Nodejs)nan 是 N odejs 抽象接口集,nan 根據當前 Nodejs 版本,使用宏判斷執行對應版本的 AP I。特點: C++ 擴展在不同版  Nodejs 中運行,需重新編譯,Nodejs 升級到較高版本后出現接口不兼容問題。
  • Node-APINode-API 使用 Nodejs 二進制接口,相比 nan 方式這些二進制接口更為穩定。特點: 不同版本 Nodejs 只要 abi 版本號一致,C++ 擴展可以直接使用無需重新編譯,消除了 Nodejs 版本差異。

構建工具 

  • node-gypnode-gyp  對 gyp(Chromium 編寫的構建工具)進行了封裝,binding.gyp 為其配置文件。node-gyp 工作分為兩個過程:a.  結合 binding.gyp 生成對應平臺下的工程配置,比如:Windwos 下生成 .sln 項目文件。b.  項目文件編譯,生成 C++ 擴展。binding.gyp 配置文件,以 Windows 為例:
{
"targets": [
{
"target_name": "addon_name",
"type": "static_library"
'defines': [
'DEFINE_FOO',
'DEFINE_A_VALUE=value',
],
'include_dirs': [
'./src/include',
'<!(node -e "require(\'nan\')")' // include NAN in your project
],
'sources': [
'file1.cc',
'file2.cc',
],
'conditions': [
[
'OS=="win"',
{
'copies': [{
'destination': '<(PRODUCT_DIR)',
'files': [
'./dll/*'
]
}],
'defines': [
'WINDOWS_SPECIFIC_DEFINE',
],
'library_dirs': [
'./lib/'
],
'link_settings': {
'libraries': [
'-lyou_sdk.lib'
]
},
'msvs_settings': {
'VCCLCompilerTool': {
'AdditionalOptions': [
'/utf-8'
]
}
},
}
]
],
},
]
}

字段說明:

  • target_name: 目標的名稱,此名稱將用作生成的 Visual Studio 解決方案中的項目名稱。
  • type: 可選項:static_library 靜態庫、executable 可執行文件、shared_library 共享庫。
  • defines: 將在編譯命令行中傳入的 C 預處理器定義(使用 -D 或 /D 選項)。
  • include_dirs: C++ 頭文件所在的目錄。
  • sources: C++ 源文件。
  • conditions: 適配不同環境配置條件塊。
  • copies: 拷貝 dll 動態庫到生成目錄。
  • library_dirs: 配置 lib 庫目錄到 vs 項目中。
  • libraries: 項目依賴的庫。
  • msvs_settings: Visual Studio 中屬性設置。

node-gyp 編譯指令:

node-gyp clean //清空上一次構建目錄
node-gyp configure //配置項目
node-gyp build //項目編譯,生成C++擴展
node-gyp rebuild //重新生成C++擴展,相當于clean configure build的結合
  • cmake-jscmake-js 與 node-gyp 工作原理類似。 cmake-js 是基于 CMake 的構建系統,而 node-gyp 是基于  Goole 的 gyp 工具,這里不在進行詳細介紹。

回調事件處理 

Nodejs 運行在單線程中,但它能夠支持高并發,就是依賴事件循環實現。簡單來說 Nodejs 主線程維護一個事件隊列,收到一個耗時任務將任務放入隊列,繼續向下執行其他任務。主線程空閑時,遍歷事件隊列,非 I/O 任務親自處理,通過回調函數返回給上層調用。I/O 任務放入線程池執行,并指定回調函數,然后繼續執行其他任務。

C++ 擴展調用 js 回調函數時,會在 Nodejs 掛在一個 libuv 線程池,用于處理回調函數,當 Nodejs 主線程空閑時,去遍歷線程池,處理任務。libuv 具體細節參考 nertc-electron-sdk:

https://github.com/netease-im/node-nertc-sdk/blob/main/nertc_sdk_node/nertc_node_engine_event_handler.cpp

03 混合編程實踐

示例1 

結合 node-addon-api 進行演示,node-addon-api 對 Node-API 接口進行了封裝開發簡單。該實例完成 js 調用 C++ 函數實現兩個數字相加。

  • 項目結構

  • package.json 配置文件
//package.json
{
"name": "addon-sdk",
"version": "0.1.0",
"description": "test nodejs addon sample",
"main": "./api/index.js",
"private": true,
"gypfile": true,
"dependencies": {
"bindings": "~1.2.1",
"node-addon-api": "^3.0.0"
},
"devDependencies": {
"node-gyp": "^8.2.0"
},
"scripts": {
"test": "node ./api/index.js"
},
"license": "ISC",
"author": "liyongqiang"
}
  • binding.gyp 配置文件
//binding.gyp
{
"targets": [
{
"target_name": "addon",
"sources": [
"./src/addon.cc",
"./src/engine.h" ,
"./src/engine.cpp"
],
"include_dirs": [
"<!@(node -p \"require('node-addon-api').include\")"
],
'defines': [
'NAPI_DISABLE_CPP_EXCEPTIONS'
]
}
]
}
  • C++ 擴展
//addon.cc
#include <napi.h>
#include "engine.h"


Napi::Object InitAll(Napi::Env env, Napi::Object exports) {
return nertc::Engine::Init(env, exports);
}


NODE_API_MODULE(addon, InitAll)


//engine.h
#pragma once
#include <napi.h>
namespace nertc {
class Engine : public Napi::ObjectWrap<Engine> {
public:
static Napi::Object Init(Napi::Env env, Napi::Object exports);
Engine(const Napi::CallbackInfo& info);
private:
Napi::Value add(const Napi::CallbackInfo& info);
};
}


//engine.cpp
#include "engine.h"
namespace nertc {
Napi::Object Engine::Init(Napi::Env env, Napi::Object exports)
{
Napi::Function func =
DefineClass(env, "Engine",
{InstanceMethod("add", &Engine::add)});
Napi::FunctionReference* constructor = new Napi::FunctionReference();
*constructor = Napi::Persistent(func);
env.SetInstanceData(constructor);
exports.Set("Engine", func);
return exports;
}


Engine::Engine(const Napi::CallbackInfo& info): Napi::ObjectWrap<Engine>(info) {}


Napi::Value Engine::add(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();//獲取環境變量
int ret = 0;
int length = info.Length();//獲取參數個數
if (length != 2 || !info[0].IsNumber() || !info[1].IsNumber())
{
Napi::TypeError::New(env, "Number expected").ThrowAsJavaScriptException();
ret = -1;
return Napi::Number::New(env, ret);
}
int num1 = info[0].As<Napi::Number>().Int32Value();//獲取第一個參數
int num2 = info[1].As<Napi::Number>().Int32Value();////獲取第二個參數
int sum = num1 + num2;
return Napi::Number::New(env, sum);//返回結果到js層
}
}
  • js 調用 C++ 擴展
var addon = require('bindings')('addon');//調用C++擴展
var engine = new addon.Engine();
console.log( `num1 + num2 = ${engine.add(1,2)}`);//輸出3

在 package.json 目錄下,執行 npm install、npm run test,可以看到 js 調用 C++ 接口成功,輸出兩個數字相加結果。

示例2 

網易云信音視頻通話 nertc-electron-sdk,采 Node-API 方式進行開發,將 C++ 原生 sdk 封裝成 Nodejs 模塊(nertc-electron-sdk.node),結合 Electron 可以快速實現音視頻通話。github demo 體驗地址:

https://github.com/netease-im/Basic-Video-Call/tree/master/Group-Video/NERtcSample-GroupVideoCall-Electron

04  常見問題

  • Electron 應用中 js 調用 C++ 擴展時,提示 Error: The specified module could not be found。
    答:該錯誤表示能找到 C++ 擴展模塊(.node)但是加載失敗,因為 .node 會依賴其他 .dll 和 C++ 運行庫,缺少這些庫時就會報上面的錯誤,使用 depends 查看缺少哪種庫,配置即可。
  • 運行使用 C++ 擴展的 Electron 應用,提示 The specifield module could not be found。
    答:該錯誤表示找不到 C++ 擴展模塊。在項目 package.json 文件中配置 extraFiles 字段,將擴展拷貝到 Electron 可加載目錄即可。
  • Electron 加載 C++ 擴展時提示:Module parse failed: Unexpected character '?'。
    答:webpack 只能識別 js 和 json 文件無法識別 C++ 擴展模式,在 Electron 打包時需要在 vue.config.js 中配置 C++ 擴展的 loader。
  • 更多常見問題匯總:
    ?https://doc.yunxin.163.com/docs/jcyOTA0ODM/jU4NTEwNzg?platformId=50456#9


責任編輯:張燕妮 來源: 網易智企技術+
相關推薦

2022-08-04 10:12:49

桌面技術

2023-02-01 18:33:44

得物商家客服

2021-06-02 09:27:56

ElectronPepper Flas插件

2020-10-27 13:19:33

架構APICloud多端

2024-12-03 11:59:53

2021-09-13 14:19:03

HudiLakehouse阿里云

2022-01-24 12:38:58

Vite插件開發

2018-01-11 17:22:20

PHP大數據開發

2023-12-26 10:04:29

Electron應用開發框架

2019-01-15 09:10:17

邊緣計算數據中心IT

2024-04-28 14:22:25

鯤鵬

2021-06-29 18:26:34

數字媒體騰訊云數據庫

2009-06-04 20:26:45

2020-11-05 10:40:18

ActiveMQ

2017-06-13 09:17:17

手機QQQzone

2019-10-29 09:48:20

ElectronGithub開源庫

2018-01-08 14:31:09

Electron桌面APP前端

2023-01-31 15:27:13

數據治理數據管理

2019-07-22 10:42:11

React組件前端
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 天堂亚洲| 国产精品视频免费播放 | 毛片一级网站 | 中文av电影 | 久久一区二区免费视频 | 在线观看第一区 | 成人在线免费 | 国产午夜视频 | 欧美精品在线一区 | 亚洲性在线 | 国产激情片在线观看 | 日韩视频在线一区 | 免费黄色录像片 | 国产精品美女视频 | 国产精品久久久久久久久久久久久久 | 久久久99国产精品免费 | 亚洲精品二区 | 在线一区视频 | 四虎网站在线观看 | 欧美性一区二区三区 | 国产二区三区 | 精品欧美一区二区精品久久久 | 精品日韩 | 日本a视频| 欧美成人精品欧美一级 | 天天草天天干天天 | 国产999精品久久久影片官网 | 欧美一级黄色片 | 国产一区在线免费 | 亚洲欧美日韩精品久久亚洲区 | 国产精品视频一区二区三区 | 免费黄色片在线观看 | 色网在线看 | 久久久久久久国产 | 91九色网站 | 亚洲视频在线观看一区二区三区 | 精品一区二区三区av | 狠狠久久| 日韩在线播放视频 | 91大神在线资源观看无广告 | 日本久久精品视频 |