Господи Иисусе, это JSON Bourne ...

Прочитав Часть 1 этой серии, вы, вероятно, подумаете: Черт побери, как легко написать и скомпилировать собственный нодовой модуль узла из кода C ++. Это все, что мне нужно знать? Что ж, для начала достаточно. В «Части 1 мы передавали только плоские значения и экземпляры нашего векторного класса туда и обратно. Однако в какой-то момент вы, вероятно, также захотите передать массивы, объекты JSON или функции в свой C ++ API. Поэтому пора копнуть глубже.

В этой статье вы найдете краткий обзор того, как:

  • передавать массивы JS в собственный аддон и как получить доступ к его элементам
  • передать объекты JSON в собственный аддон и прочитать его свойства
  • создавать массивы JS и объекты JSON из C ++ и возвращать их в свое приложение JS
  • обрабатывать обратные вызовы и вызывать функции JS из C ++

Работа с массивами:

Распаковывать массивы довольно просто. Мы преобразуем v8 :: Value в v8 :: Array, перебираем массив и нажимаем каждый элемент в std :: vector, простую коллекцию, которая в C ++ эквивалентна массиву JS или List в Java, если вы хотите видеть это таким.

Каждый элемент в массиве - это v8 :: Value, который необходимо развернуть в зависимости от того, какой у него тип. Вы также можете передать массив экземпляров класса и развернуть каждый элемент, как мы это делали с векторами в Часть 1. Вы также можете передать массив объектов JSON или массив массивов. Однако имейте в виду, что массив JS может содержать элементы разных типов, поскольку он не типизирован, как в C ++.

Создать массив и вернуть его из вызова собственной функции можно следующим образом:

Работа с JSON:

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

В частности, я счел полезным возвращать объект JSON, содержащий возвращаемые значения, когда вызов функции должен возвращать несколько данных. В C ++ вам нужно будет передать ссылку на любое другое возвращаемое значение в качестве аргумента функции.

Кроме того, может быть очень удобно передавать необязательные параметры в виде объекта JSON. Таким образом, пользователю вашего API не нужно повторно вводить и запоминать все параметры по умолчанию, если они хотят изменить только параметры в конце сигнатуры функции.

Мы можем читать свойства объекта JSON, предполагая, что объект с ключами «foo» и «bar», например

{ foo: 123, bar: 'hi' }

нравится:

Доступ к свойствам осуществляется через v8 :: Strings. С помощью Nan :: HasOwnProperty (obj, key) мы можем проверить, действительно ли объект имеет определенный ключ свойства, прежде чем мы получим доступ к значению. Nan :: Get вернет соответствующее значение, которое мы должны развернуть.

Создание объекта JSON работает наоборот. Сначала мы создаем новый объект, а затем устанавливаем произвольные свойства как пары ключ-значение для объекта с помощью Nan :: Set (obj, key, value):

Это должно вернуть следующий объект JSON:

{ foo: 456, bar: 'awesome' }

Использование обратных вызовов:

Обратные вызовы являются неотъемлемой частью модели асинхронного программирования JavaScript, а также для Node.js. В части 3 этой серии я покажу вам, как писать асинхронные привязки к вашему собственному модулю узла через AsyncWorkers.

Кроме того, обратные вызовы могут использоваться как средство вызова JS-функции из вашего модуля C ++. Допустим, мы хотим передать следующую функцию:

function isFoo (str) {
  return str === ‘foo’;
}

Если мы передадим функцию встроенному вызову, мы сможем создать из него Nan :: Callback и вызвать его с помощью cb.Call (argc, args ):

Вызов функции из C ++ выполняется точно так же, как мы делали с вызовом конструктора Vector для создания нового экземпляра из C ++ в Часть 1 . Мы должны передать количество аргументов argc и аргументы в виде массива v8 :: Values ​​. Из cb.Call мы получаем результат, например возвращаемое значение нашей JS-функции в виде v8 :: Value.

Требуется введение в разработку собственных надстроек для Node.js? Посмотрите Часть 1.

Хотите создать модуль асинхронного узла? Посмотрите Часть 3.