mirror of
https://github.com/Estom/notes.git
synced 2026-04-15 02:39:56 +08:00
js
This commit is contained in:
148
NodeJS/11C++插件.md
Normal file
148
NodeJS/11C++插件.md
Normal file
@@ -0,0 +1,148 @@
|
||||
## 1 应用场景
|
||||
|
||||
### Automation
|
||||
如果您的c++运行作为一个独立的命令行,您不需要源代码来利用选项1 -automation 选项。您可以使用Node的子进程API 运行您的c++程序。这个选项适用于将任何东西带到web上——如果你只是运行它的话,你的命令行程序写在什么语言上并没有什么区别。如果您正在阅读这篇文章,希望获得C代码、Fortran代码或其他一些语言,那么这个选项值得一读。
|
||||
|
||||
自动化选项不仅仅针对那些没有c++代码的人。如果您有c++代码,或者可以很容易地转换成命令行程序,那么这个选项是合理的,如果您可以使用性能,并且您并不想陷入语言集成的麻烦中。
|
||||
|
||||
### Shared Library / DLL
|
||||
如果您处理的是c++ dll/lib,或者您有c++源代码,并且可以进行适当的修改,以创建动态库,那么 shared library 方法可能对您很有效。在本章中,我们将详细介绍如何使用外部函数接口模块进行此操作。这个选项可以让您更精确地控制如何将c++集成到节点中,因为对c++例程的调用通常可以直接写到Node.js代码中。虽然这种方法可以使您更接近完整的集成,但是您仍然需要处理类型转换和在调用c++时阻塞。如果您想要更好的集成,这是一个很好的选择,而无需花费大量时间来处理V8。
|
||||
|
||||
### Node.js Addon
|
||||
如果您有c++源代码,那么第三个选项是创建一个本机 Node.js模块调用你的c++。虽然这是一个更具挑战性的方法,但是您获得了大量的灵活性和性能。您还可以选择异步调用您的c++,这样您就不会阻塞web应用程序的事件循环,而c++正在处理数字。当我们在本节中介绍这部分内容时,它将主要作为对书中主要章节中已经介绍的材料的回顾。
|
||||
|
||||
## 2 插件实现
|
||||
|
||||
### 主要的方案
|
||||
> 当前主流的方法,就是最简单的napi。下面是其发展过程。
|
||||
* 使用nodejs和v8原生的API实现C++接口的编译工作.是nodejs和V8引擎原生的API,代码级别的API。会随着版本进行演进,并且十分难搞。
|
||||
* 使用第三方的nan库进行API实现。也已经淘汰。
|
||||
* 使用N-API实现C++接口的编译工作。经过nodejs官方封装的二进制借口文件,ABI。接口稳定,并且向后兼容。
|
||||
* 使用EFF网络中的调用DLL的方法。
|
||||
|
||||
|
||||
## 3 n-api
|
||||
### 背景
|
||||
* 以 C 的风格提供稳定 ABI 接口;
|
||||
* 消除 Node.js 版本的差异;
|
||||
* 消除 JavaScript 引擎的差异(如 Google V8、Microsoft ChakraCore 等)
|
||||
|
||||
### 特性
|
||||
* 提供头文件 node_api.h;
|
||||
* 任何 N-API 调用都返回一个 napi_status 枚举,来表示这次调用成功与否;
|
||||
* N-API 的返回值由于被 napi_status 占坑了,所以真实返回值由传入的参数来继承,如传入一个指针让函数操作;
|
||||
* 所有 JavaScript 数据类型都被黑盒类型 napi_value 封装,不再是类似于 v8::Object、v8::Number 等类型;
|
||||
* 如果函数调用不成功,可以通过 napi_get_last_error_info 函数来获取最后一次出错的信息。
|
||||
|
||||
### 初始化
|
||||
* 引入头文件
|
||||
|
||||
```C
|
||||
#define NAPI_VERSION 3//NAPI_VERSION for the given release of Node.js.
|
||||
#include <node_api.h>
|
||||
```
|
||||
|
||||
```C
|
||||
void Init(napi_env env, napi_value exports, napi_value module, void* priv)
|
||||
{
|
||||
napi_status status;
|
||||
|
||||
// 用于设置 exports 对象的描述结构体
|
||||
napi_property_descriptor desc =
|
||||
{ "echo", 0, Echo, 0, 0, 0, napi_default, 0 };
|
||||
|
||||
// 把 "echo" 设置到 exports 去
|
||||
status = napi_define_properties(env, exports, 1, &desc);
|
||||
}
|
||||
|
||||
NAPI_MODULE(addon, Init)
|
||||
```
|
||||
napi_property_descriptor 是用于设置对象属性的描述结构体,它的声明如下:
|
||||
```
|
||||
|
||||
|
||||
typedef struct {
|
||||
const char* utf8name;
|
||||
|
||||
napi_callback method;
|
||||
napi_callback getter;
|
||||
napi_callback setter;
|
||||
napi_value value;
|
||||
|
||||
napi_property_attributes attributes;
|
||||
void* data;
|
||||
} napi_property_descriptor;
|
||||
```
|
||||
|
||||
### 函数声明
|
||||
通过 napi_get_cb_info 获取当次函数请求的参数信息,包括参数数量和参数体(参数体以 napi_value 的数组形式体现);
|
||||
```
|
||||
napi_value Echo(napi_env env, napi_callback_info info)
|
||||
{
|
||||
napi_status status;
|
||||
|
||||
size_t argc = 1;
|
||||
napi_value argv[1];
|
||||
status = napi_get_cb_info(env, info, &argc, argv, 0, 0);
|
||||
if(status != napi_ok || argc < 1)
|
||||
{
|
||||
napi_throw_type_error(env, "Wrong number of arguments");
|
||||
return 0; // napi_value 实际上是一个指针,返回空指针表示无返回值
|
||||
}
|
||||
|
||||
return argv[0];
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## 4 构建
|
||||
### C/C++编译工具
|
||||
* Linux
|
||||
```
|
||||
gcc编译环境
|
||||
```
|
||||
* windows
|
||||
```
|
||||
visual Studio offers all the required compiler tools. \\or
|
||||
npm install --global windows-build-tools
|
||||
```
|
||||
|
||||
|
||||
### node-gyp构建工具
|
||||
* node-gyp 是基于 GYP4 的。它会识别包或者项目中的 binding.gyp5 文件,然后根据该配置文件生成各系统下能进行编译的项目,如 Windows 下生成 Visual Studio 项目文件(*.sln 等),Unix 下生成 Makefile。在生成这些项目文件之后,node-gyp 还能调用各系统的编译工具(如 GCC)来将项目进行编译,得到最后的动态链接库 *.node 文件。
|
||||
* 项目构建的描述文件binding.gpy
|
||||
```
|
||||
{
|
||||
"targets": [{
|
||||
"target_name": "addon1",
|
||||
"sources": [ "1/addon.cc", "1/myobject.cc" ]
|
||||
}, {
|
||||
"target_name": "addon2",
|
||||
"sources": [ "2/addon.cc", "2/myobject.cc" ]
|
||||
}, {
|
||||
"target_name": "addon3",
|
||||
"sources": [ "3/addon.cc", "3/myobject.cc" ]
|
||||
}, {
|
||||
"target_name": "addon4",
|
||||
"sources": [ "4/addon.cc", "4/myobject.cc" ]
|
||||
}cmake-jsre:通过当前目录的 binding.gyp 生成项目文件,如 Makefile 等;
|
||||
$ node-gyp build:将当前项目进行构建编译,前置操作必须先 configure;
|
||||
$ node-gyp clean:清理生成的构建文件以及输出目录,说白了就是把目录清理了;
|
||||
$ node-gyp rebuild:相当于依次执行了 clean、configure 和 build;
|
||||
$ node-gyp install:手动下载当前版本的 Node.js 的头文件和库文件到对应目录。
|
||||
```
|
||||
|
||||
* 在我们编译一个 C++ 原生扩展的时候,它会去指定目录下(通常是 ~/.node-gyp 目录下)搜我们当前 Node.js 版本的头文件和静态连接库文件。
|
||||
### cmake-js构建工具
|
||||
|
||||
CMake.js is an alternative build system based on CMake.CMake.js is a good choice for projects that already use CMake or for developers affected by limitations in node-gyp.
|
||||
|
||||
|
||||
## 5 步骤
|
||||
|
||||
1. 首先使用v8编写nodejs支持的C++接口文件。或者使用n-api
|
||||
2. 然后编写binding.gyp,使用node-gyp配置并将C++文件编译成nodejs的模块。其中,调用了cmake编译工具进行搬移。
|
||||
3. 然后在js文件中引入模块。调用并输出结果。
|
||||
0
NodeJS/12Electron.md
Normal file
0
NodeJS/12Electron.md
Normal file
0
工作日志/2020年9月10日.md
Normal file
0
工作日志/2020年9月10日.md
Normal file
@@ -2,8 +2,8 @@
|
||||
|
||||
## 技术范式
|
||||
|
||||
> 1. 选择合适的技术范式。√
|
||||
> 2. 对技术细节进行学习了解
|
||||
> 1. 选择合适的技术范式。√====>electron
|
||||
> 2. 对技术细节进行学习了解√====>javascript,nodejs,electron
|
||||
> 3. 寻找开源的模板代码搭建框架
|
||||
> 4. 根据任务需求进行快速开发
|
||||
|
||||
|
||||
Reference in New Issue
Block a user