Рубрики
Без рубрики

Как создать аддоны C / C ++ в узле

Автор оригинала: Scott Robinson.

Node.js отлично подходит для многих причин, одна из которых является скоростью, в которой вы можете создавать значимые приложения. Однако, как мы все знаем, это приходит по цене производительности (по сравнению с родным кодом). Чтобы обойти это, вы можете написать свой код в интерфейс с более быстрым кодом, написанным в C или C ++. Все, что нам нужно сделать, это позволить узлу знать, где найти этот код и как взаимодействовать с ним.

Есть несколько способов решить эту проблему в зависимости от того, какой уровень абстракции вы хотите. Начнем с самой низкой абстракции, которая является узлом Аддон Отказ

Адонсы

Аддон работает, предоставляя клей между узлами и библиотек C/C ++. Для типичного разработчика узла это может быть немного сложно, поскольку вам придется войти, чтобы фактически написать код C/C ++ для настройки интерфейса. Однако между этой статьей и документацией узла вы должны быть в состоянии получить несколько простых интерфейсов.

Есть несколько вещей, которые нам нужно перейти, прежде чем мы сможем перейти к созданию аддонов. Прежде всего, нам нужно знать, как скомпилировать (что-то разработчики узлов счастливо забывают) нативный код. Это делается с использованием Узел-GYP Отказ Тогда мы кратко поговорим о Нан , который помогает при обращении с разными версиями узла API.

узел-gyp.

Существует много разных видов процессоров (X86, ARM, PowerPC и т. Д.) и еще больше операционных систем для решения при составлении вашего кода. К счастью, Узел-GYP обрабатывает все это для вас. Как описано их страницей GitHub, Узел-GYP является «поперечным инструментом командной строки, написанные в Node.js для компиляции нативных аддоновных модулей для Node.js». По сути, Узел-GYP это просто обертка вокруг GYP , что сделано командой хрома.

Readme проекта имеет несколько отличных инструкций о том, как установить и использовать пакет, поэтому вы должны прочитать это для более подробной информации. Короче, использовать Узел-GYP Вы должны сделать следующее.

Перейти к каталогу вашего проекта:

$ cd my_node_addon

Создайте соответствующие файлы сборки, используя Настроить . Команда, которая создаст либо Makefile (на UNIX) или vcxproj (В окнах):

$ node-gyp configure

И, наконец, построить проект:

$ node-gyp build

Это будет генерировать /построить каталог, содержащий, среди прочего, скомпилированные двоичные.

Даже при использовании более высоких абстракций, таких как FFI Пакет, все еще хорошо понимать, что происходит под капотом, поэтому я бы порекомендовал вам потратить время, чтобы узнать INS и outs Узел-GYP Отказ

нан

Нан (Нативные абстракции для узла) – это легко упущенный модуль, но он сэкономит вам часы разочарования. Между узлами версий v0.8 , v0.10 и V0.12 В версиях V8 использовались несколько больших изменений (в дополнение к изменениям в самом узле), поэтому Нан Помогает скрыть эти изменения от вас и предоставляет хороший, последовательный интерфейс.

Эта родная абстракция работает, предоставляя объекты/C/C ++/функции в #include файл заголовка.

Чтобы использовать его, установите Нан упаковка:

$ npm install --save nan

Добавьте эти строки в файл Binding.gyp:

"include_dirs" : [ 
    "

И вы готовы использовать Методы/Функции от nan.h внутри ваших крючков вместо оригинала #include код. Я очень рекомендую вам использовать Нан Отказ В этом случае нет большого значения в повторном изобретении колеса в этом случае.

Создание аддона

Прежде чем начать на вашем дополнении, убедитесь, что вы забираете некоторое время, чтобы ознакомиться со следующими библиотеками:

  • Библиотека V8 JavaScript C ++, которая используется для фактически взаимодействия с JavaScript (например, создание функций, вызывающих объекты и т. Д.).
    • Примечание : Node.h Предлагается ли файл по умолчанию, но действительно nan.h следует использовать вместо
  • Libuv , кроссплатформенная асинхронная библиотека ввода/вывода, написанная в C. Эта библиотека полезна при выполнении любого типа ввода/вывода (открытие файла, запись в сеть, установка таймера и т. Д.) В ваших собственных библиотеках, и вам нужно сделать его асинхронным.
  • Внутренние библиотеки узлов. Один из самых важных объектов, чтобы понять это Узел:: ObjectWrap , какие большинство предметов происходят от.

На протяжении всей остальной части этого раздела я пойду на тебя через реальный пример. В этом случае мы будем создавать крючок к C ++ Библиотека Пау функция. Так как вы почти всегда должны использовать Нан Это то, что я буду использовать на протяжении всех примеров.

Для этого примера в вашем проекте Addon вы должны иметь как минимум эти файлы:

  • POW.CPP.
  • Binding.gyp.
  • Package.json.

Файл C ++ не должен быть назван POW.CPP , но имя обычно отражается, что это дополнительный, либо его конкретная функция.

// pow.cpp
#include 
#include 

void Pow(const Nan::FunctionCallbackInfo& info) {

	if (info.Length() < 2) {
		Nan::ThrowTypeError("Wrong number of arguments");
		return;
	}

	if (!info[0]->IsNumber() || !info[1]->IsNumber()) {
		Nan::ThrowTypeError("Both arguments should be numbers");
		return;
	}

	double arg0 = info[0]->NumberValue();
	double arg1 = info[1]->NumberValue();
	v8::Local num = Nan::New(pow(arg0, arg1));

	info.GetReturnValue().Set(num);
}

void Init(v8::Local exports) {
	exports->Set(Nan::New("pow").ToLocalChecked(),
				 Nan::New(Pow)->GetFunction());
}

NODE_MODULE(pow, Init)

Обратите внимание, что нет запятой ( ; ) в конце Node_Module Отказ Это делается намеренно с Node_Module На самом деле не функция – это макрос.

Приведенный выше код может сначала казаться немного пугающим для тех, кто не написал какой-либо C ++ в течение некоторого времени (или никогда), но это действительно не слишком трудно понять. Пау Функция – это мясо кода, в котором мы проверяем количество аргументов, типы аргументов, позвоните на родной Пау Функция и вернуть результат к приложению узла. Информация Объект содержит все о вызове, которое нам нужно знать, включая аргументы (и их типы) и место для возврата результата.

Init Функция в основном просто ассоциирует Пау Функция с «Пау» имя, и Node_Module Макрос на самом деле ручки регистрации аддона с узлом.

Package.json Файл не сильно отличается от обычного узла модуля. Хотя, похоже, не требуется, большинство модулей Addon имеют "Gypfile": правда Установите в них, но процесс сборки, похоже, все еще работает нормально без него. Вот что я использовал для этого примера:

{
  "name": "addon-hook",
  "version": "0.0.0",
  "description": "Node.js Addon Example",
  "main": "index.js",
  "dependencies": {
    "nan": "^2.0.0"
  },
  "scripts": {
    "test": "node index.js"
  }
}

Далее этот код должен быть встроен в файл «POW.NODE», который является двоичным аддоном. Для этого вам нужно сказать Узел-GYP Какие файлы ему необходимо компилировать, а именно бинарное имя файла. Хотя есть много других вариантов/конфигураций, которые вы можете использовать с Узел-GYP Для этого примера нам не нужно много. Binding.gyp Файл может быть таким же простым, как:

{
	"targets": [
		{
			"target_name": "pow",
			"sources": [ "pow.cpp" ],
			"include_dirs": [
				"

Теперь, используя Узел-GYP Создайте соответствующие файлы сборки проекта для данной платформы:

$ node-gyp configure

И, наконец, построить проект:

$ node-gyp build

Это должно привести к Pow.node созданный файл, который будет проживать в Build/Release/ каталог. Чтобы использовать этот крючок в вашем приложении, просто требуется В Pow.node Файл (Sans the ‘.Node’ расширение):

var addon = require('./build/Release/pow');

console.log(addon.pow(4, 2));		// Prints '16'

Узел внешний интерфейс

Примечание : FFI Пакет ранее известен как Узел-FFI Отказ Обязательно добавьте новее FFI Имя к вашим зависимостям, чтобы избежать большого растерянности во время NPM установить 🙂

Хотя функциональность аддона, предоставленная узлом, дает вам все необходимое гибкость, не все разработчики/проекты понадобится. Во многих случаях абстракция, как FFI будет делать все хорошо, и обычно требуется очень мало, чтобы без программирования C/C ++.

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

var ffi = require('ffi');

var libm = ffi.Library('libm', {
	'pow': [ 'double', [ 'double', 'double' ] ]
});

console.log(libm.pow(4, 2));	// 16

Приведенный выше код работает, указав библиотеку для загрузки (LIBM) и, в частности, какие методы нагрузки из этой библиотеки (POW). [«Двойной», [«Двойной», «Двойной»]] линия рассказывает FFI Какой тип возврата и параметры метода есть, что в этом случае два Двойной Параметры и A Двойной вернулся.

Заключение

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

Есть ли какие-либо примеры библиотек, которые вы хотели бы видеть привязки? Дайте нам знать об этом в комментариях!