Собственные модули Node с Rust и Neon

Привет мир!

Сегодня я хочу показать вам быстрый и простой способ создания нативных модулей для nodejs.

Контекст

В настоящее время nodejs является одним из самых быстрых языков, особенно в области веб-разработки и серверной части. Кроме того, его V8 ядро ​​постоянно совершенствуется, и большинство его основных модулей написаны на чистом C++.

К сожалению, nodejs не хватает мощности для тяжелой обработки чисел и сложных вычислений. Но гениальная команда nodejs дала нам возможность встроить нативные модули, чтобы преодолеть это препятствие. А с недавними изменениями в N-Api и появлением языка Rust это можно легко сделать, избегая крутой кривой обучения C++.

Мы воспользуемся этой мощью с помощью пакета neon и напишем простой нативный модуль, который можно будет включить в ваши nodejs проекты.

Установка

Для начала разработки нативного модуля вам понадобится компилятор Rust, который вы можете получить на домашней странице Rust.

Затем установим пакет neon из npm:

npm i -g neon-cli

Проект

Создать новый проект neon так же просто, как создать проект nodejs. Просто беги

neon new <PROJECTNAME>

и вам будет представлен npm подобный диалог вопроса. В конце neon создаст папку с вашим ‹PROJECTNAME›, содержащую все необходимые файлы.

Код

В этой папке вы найдете native/src/lib.rs. В этих файлах находится ваш собственный код. Давайте быстро посмотрим:

#crate is like rusts npm telling rust to use the neon package 
extern crate neon; 
#using some stuff from neon namespace, you may compare it to require
use neon::prelude::*; 
#this is the function the module will execute 
fn hello(mut cx: FunctionContext) -> JsResult<JsString> { 
  Ok(cx.string("hello node")) 
} 
#here the function is exported, you may compare it to module.exports register_module!(mut cx, { 
  cx.export_function("hello", hello) 
});

Важными частями являются cx и -> JsResult<JsString>.

Последний указывает возвращаемый тип функции, а также является самым большим преимуществом использования neon (помимо очень простого и быстрого рабочего процесса). Возвращаемое значение уже будет отформатировано таким образом, что nodejs может его интерпретировать, что особенно удобно при работе с объектами и т.п.

cx представляет контекст функций, который в некотором роде является средой выполнения V8. Как и в приведенном выше примере, где cx.string используется для создания строкового представления, которое можно использовать в функции, а также понимать и работать с ним в nodejs.

Мы обновим эту функцию, чтобы получить параметр, который должен быть возвращен вместо «hello node».

fn hello(mut cx: FunctionContext) -> JsResult<JsString> { 
  let greetee = cx.argument::<JsString>(0)?.value();
  Ok(cx.string("Hello ".to_owned() + &greetee)) 
}

cx.argument::(0)?.value(); получит первый аргумент, переданный функции, а также гарантирует, что он имеет строковый тип. Это очень удобно и еще один кирпичик в стене простоты пакета neon.

Конкатенация в Rust немного сложнее, чем в nodejs из-за того, что вы отвечаете за управление памятью... это глава для другого дня... глава в книжном формате. А пока просто скопируйте и вставьте и будьте благодарны за nodesjs простоту.

Интерфейс для нашей вновь созданной функции расположен по адресу lib/index.js. Мы меняем его содержимое на

var addon = require("../native"); 
module.exports = { 
  greet: addon.hello 
};

После этого мы закончили с частью кодирования, но, поскольку это нативный код, мы должны скомпилировать его в машинный код. Также книжная следующая глава. Но neon хорошо о нас позаботился.

neon build

Просто запустите эту команду, и neon позаботится о компиляции и создаст для нас нативный модуль. Теперь мы можем проверить это в REPL nodejs.

$ node 
> const greeter = require('.') 
> greeter.greet() 
TypeError: not enough arguments 
greeter.greet(1) 
TypeError: failed downcast to string 
greeter.greet("World") 
'Hello World'

Поздравляем, вы написали свой первый нативный модуль. С этого момента вы можете либо опубликовать его, либо использовать через npm link в своих проектах.

Вы можете проверить весь код здесь.

На этом этот пост заканчивается.

Большое спасибо за внимание и хорошего дня ❤
Оставайтесь без ошибок, друзья

предыдущий пост

Создание и публикация пакета npm

Первоначально опубликовано на abe.codes 13 января 2019 г.