Node.js a le meilleur effet dans l'écriture de backends en utilisant JavaScript, et cela vaut la peine d'essayer plus. Cependant, si vous avez besoin de certaines fonctions qui ne peuvent pas être utilisées directement ou même des modules qui ne peuvent pas être implémentés du tout, pouvez-vous introduire de telles réalisations à partir de la bibliothèque C / C ++? La réponse est oui. Tout ce que vous avez à faire est d'écrire un plugin et d'utiliser d'autres ressources de base de code dans votre code JavaScript. Commençons ensemble le voyage d'enquête d'aujourd'hui.
introduire
Comme Node.js le dit dans la documentation officielle, les plug-ins sont des objets partagés qui lient dynamiquement, ce qui peut connecter le code JavaScript avec les bibliothèques C / C ++. Cela signifie que nous pouvons référencer n'importe quoi de la bibliothèque C / C ++ et l'incorporer dans Node.js en créant des plugins.
Par exemple, nous créerons une encapsulation pour l'objet standard std :: String.
Préparation
Avant de commencer à écrire, nous devons nous assurer que nous avons préparé tous les matériaux nécessaires à la compilation ultérieure des modules. Tout le monde a besoin de nœuds et de toutes les dépendances. Vous pouvez utiliser la commande suivante pour installer Node-Gyps:
npm install -g nœud-gyp
En termes de dépendances, nous devons préparer les projets suivants pour les systèmes UNIX: • Python (nécessite la version 2.7, 3.x ne peut pas fonctionner correctement)
• faire
• Une chaîne d'outils du compilateur C ++ (comme GPP ou G ++)
Par exemple, sur Ubuntu, vous pouvez utiliser la commande suivante pour installer tous les projets ci-dessus (Python 2.7 aurait dû être préinstallé):
sudo apt-get install build-essentiels
Dans l'environnement du système Windows, ce dont vous avez besoin est:
• Python (version 2.7.3, 3.x ne peut pas fonctionner normalement)
• Microsoft Visual Studio C ++ 2010 (pour Windows XP / Vista)
• Microsoft Visual Studio C ++ 2012 pour Windows Desktop (pour Windows 7/8)
Pour souligner, la version express de Visual Studio peut également fonctionner normalement.
Fichier Binding.gyp
Ce fichier est utilisé par Node-GYP et est conçu pour générer le fichier de construction approprié pour notre plugin. Vous pouvez cliquer ici pour afficher le document de description du fichier .gyp fourni par Wikipedia, mais l'exemple que nous voulons utiliser aujourd'hui est très simple, vous avez donc juste besoin d'utiliser le code suivant:
?
où Target_name peut être défini sur tout ce que vous voulez. Le tableau des sources contient tous les fichiers source que le plug-in doit utiliser. Dans notre exemple, addon.cc est également inclus, qui est utilisé pour tenir compte du code nécessaire pour compiler les plugins et stdstring.cc, plus notre classe d'encapsulation.
Classe StdStringwrapper
La première étape consiste à définir notre propre classe dans le fichier stdstring.h. Si vous connaissez la programmation C ++, vous ne serez certainement pas familier avec les deux lignes de code suivantes.
#ifndef stdstring_h #define stdstring_h
Cela appartient à la norme inclut la garde. Ensuite, nous devons inclure les deux en-têtes suivants dans la catégorie Inclure:
#inclure
#inclure
Le premier s'adresse à la classe STD :: String, tandis que les seconds incluent les agits sur tous les nœuds et le contenu lié à V8.
Une fois cette étape terminée, nous pouvons déclarer notre classe:
classe StDStringwrapper: Node public :: objectwrap {
Pour toutes les classes que nous avons l'intention d'inclure dans le plugin, nous devons étendre la classe Node :: ObjectWrap.
Nous pouvons maintenant commencer à définir la propriété privée de cette classe:
privé: std :: string * s_; Explicite stdstringwrapper (std :: string s = ""); ~ StDstringwrapper ();
En plus des constructeurs et des fonctions analytiques, nous devons également définir un pointeur pour Std :: String. Ceci est le cœur de cette technologie et peut être utilisé pour connecter la base de code C / C ++ au nœud - nous définissons un pointeur privé pour la classe C / C ++ et utilisons ce pointeur pour implémenter les opérations dans toutes les méthodes suivantes.
Maintenant, nous déclarons la propriété statique du constructeur, qui fournira des fonctions pour la classe que nous avons créée dans V8:
V8 statique :: constructeur persistant;
Les amis intéressés peuvent cliquer ici pour se référer au modèle de description du modèle pour plus de détails.
Maintenant, nous avons également besoin d'une nouvelle méthode, qui sera affectée au constructeur mentionné ci-dessus, et V8 inimialisera notre classe:
statique v8 :: manipuler nouveau (const v8 :: arguments & args);
Chaque fonction agissant sur V8 devrait suivre les exigences suivantes: il acceptera les références à V8 :: Arguments des objets et renvoie un Handle V8 :: Handle> V8 :: Valeur> - c'est exactement la façon dont V8 traite du JavaScript de type faible lorsque vous utilisez un codage C ++ de type fort.
Après cela, nous devons insérer deux autres méthodes dans le prototype de l'objet:
V8 :: Handle Add (const v8 :: arguments & args); statique v8 :: manipuler toString (const v8 :: arguments & args);
où la méthode toString () nous permet d'obtenir la valeur de S_ au lieu de la valeur de [objet objet] lors de l'utilisation avec une chaîne JavaScript normale.
Enfin, nous introduirons la méthode d'initialisation (cette méthode sera appelée par V8 et affectée à la fonction du constructeur) et Close Inclure Guard:
public: static void init (v8 :: greatp exportts); }; #endif
Le rôle de l'objet d'exportation dans le module JavaScript est équivalent à module.exports.
Fichier, constructeur et fonction d'analyse stdstring.cc
Créez maintenant le fichier stdstring.cc. Nous devons d'abord inclure notre en-tête:
#include "Stdstring.h"
Ce qui suit définit la propriété du constructeur (car elle appartient à une fonction statique):
V8 :: StdStringwrapper persistant :: Constructeur;
Ce constructeur servant la classe attribuera l'attribut S_:
StdStringWrapper :: StdStringWrapper (std :: String S) {s_ = new std :: string (s); }Et la fonction d'analyse le supprimera pour éviter le débordement de la mémoire:
StdStringwrapper :: ~ stdstringwrapper () {delete s_; }De plus, vous devez supprimer tout le contenu attribué avec de nouveaux, car chaque fois que cette situation peut entraîner une exception, veuillez vous souvenir des opérations ci-dessus ou utiliser un pointeur partagé.
Méthode INIT
Cette méthode sera appelée par V8 et est destinée à initialiser notre classe (attribuer le constructeur et placer tout le contenu que nous avons l'intention d'utiliser dans JavaScript dans l'objet Exportts):
void stdstringwrapper :: init (v8 :: great les exportations) {
Tout d'abord, nous devons créer un modèle de fonction pour notre nouvelle méthode:
v8 :: local tpl = v8 :: functionTemplate :: new (new);
C'est un peu similaire à la nouvelle fonction en JavaScript - cela nous permet de préparer nos propres classes JavaScript.
Maintenant, nous pouvons définir un nom pour la fonction en fonction des besoins réels (si vous manquez cette étape, le constructeur sera à l'état anonyme, c'est-à-dire que le nom est une fonction SomeName () {} ou fonction () {}):
tpl-> setClassName (v8 :: string :: newsymbol ("stdstring"));
Nous utilisons V8 :: String :: Newsymbol () pour créer une chaîne de type spéciale pour les noms de propriétés - ce qui fait gagner un peu de temps pour le fonctionnement du moteur.
Après cela, nous devons définir le nombre de champs que notre instance de classe contient:
tpl-> instanceTemplate () -> setInternalFieldCount (2);
Nous avons deux méthodes - Add () et ToString (), nous avons donc défini le numéro sur 2. Maintenant, nous pouvons ajouter nos propres méthodes au prototype de fonction:
tpl-> prototypeTEmplate () -> set (v8 :: string :: newsymbol ("add"), v8 :: functionTemplate :: new (add) -> getFunction ());
tpl-> prototypeTEmplate () -> set (v8 :: string :: newsymbol ("toString"), v8 :: functionTemplate :: new (toString) -> getFunction ());
Cette partie du code semble assez grande, mais tant que vous observez soigneusement, vous trouverez les règles: nous utilisons TPL-> PrototyPeTEmplate () -> set () pour ajouter chaque méthode. Nous utilisons également V8 :: String :: Newsymbol () pour leur fournir des noms et FunctionTemplate.
Enfin, nous pouvons placer le constructeur dans l'objet d'exportation dans nos propriétés de classe de constructeur:
Constructor = V8 :: Persistrent :: new (tpl-> getFunction ()); Exports-> set (v8 :: string :: newsymbol ("stDstring"), constructeur); }Nouvelle méthode
Maintenant, ce que nous devons faire, c'est définir une méthode qui fonctionne de la même manière que javascript object.prototype.constructor:
V8 :: Gire StdstringWrapper :: New (const v8 :: arguments & args) {Nous devons d'abord créer une portée pour cela:
V8 :: Handlescope Scope;
Après cela, nous pouvons utiliser la méthode .isstructCall () de l'objet Args pour vérifier si le constructeur peut être appelé en utilisant le nouveau mot-clé:
if (args.isconstructCall ()) {Si vous le pouvez, nous passons d'abord le paramètre à std :: string comme suit:
v8 :: string :: utf8value str (args [0] -> toString ()); std :: string s (* str);
... afin que nous puissions le transmettre dans le constructeur de notre classe encapsulée:
StdStringwrapper * obj = new StDStringwrapper (s);
Après cela, nous pouvons utiliser la méthode .Wrap () de l'objet que nous avons créé précédemment (Hérité à partir de Node :: ObjectWrap) pour l'attribuer à cette variable:
obj-> enveloppe (args.Chis ());
Enfin, nous pouvons retourner cet objet nouvellement créé:
retourne args.tout ();
Si la fonction ne peut pas être appelée avec Nouveau, nous pouvons également appeler directement le constructeur. Ensuite, ce que nous voulons faire est de définir une constante pour le nombre de paramètres:
} else {const int argc = 1;Nous devons maintenant créer un tableau en utilisant nos propres paramètres:
v8 :: argv local [argc] = {args [0]};Ensuite, passez le résultat de la méthode Constructor-> NewInstance sur Scope.cose afin que l'objet puisse jouer un rôle plus tard (Scope.Close permet essentiellement à tout le monde de le maintenir en déplaçant la poignée de traitement de l'objet à une plage plus élevée - c'est aussi ainsi que la fonction prend effet):
return scope.close (constructeur-> newInstance (argc, argv)); }}
Ajouter la méthode
Créons maintenant la méthode ADD, qui est destinée à permettre à chacun d'ajouter du contenu à la chaîne interne STD :: de l'objet:
V8 :: Gire StdStringWrapper :: Add (const v8 :: arguments & args) {Tout d'abord, nous devons créer une plage pour notre fonction et convertir le paramètre en chaîne std :: comme avant:
V8 :: Handlescope Scope; v8 :: string :: utf8value str (args [0] -> toString ()); std :: string s (* str);
Nous devons maintenant déballer l'objet. Nous avons également effectué cette opération d'encapsulation inverse avant - cette fois, nous allons obtenir un pointeur vers l'objet de cette variable.
StdStringWrapper * obj = objectwrap :: un peu (args.this ());
Ensuite, nous pouvons accéder à l'attribut S_ et utiliser sa méthode .append ():
obj-> s _-> APPENDE (S);
Enfin, nous renvoyons la valeur actuelle de l'attribut S_ (besoin d'utiliser Scope.close à nouveau):
return scope.close (v8 :: string :: new (obj-> s _-> c_str ()));
Étant donné que la méthode v8 :: string :: new () ne peut accepter que le pointeur char comme une valeur, nous devons utiliser obj-> s _-> c_str () pour l'obtenir.
À l'heure actuelle, un répertoire de construction doit être créé dans votre dossier de plug-in.
test
Nous pouvons maintenant tester nos plug-ins. Créez un fichier test.js et les bibliothèques de compilation nécessaires dans notre répertoire de plug-in (vous pouvez dire directement l'extension .Node):
var adddon = require ('./ build / release / addon');Ensuite, créez une nouvelle instance pour notre objet:
var test = new addon.stdstring ('test');Ensuite, faites-le, comme l'ajout ou la conversion en une chaîne:
test.add ('!'); Console.log ('Test /' S contenu:% s ', test);Après l'exécution, vous devriez voir les résultats d'exécution suivants dans la console:
en conclusion
J'espère qu'après avoir lu ce tutoriel, vous pouvez dissiper vos préoccupations et considérer la création et les tests de plug-ins Node.js personnalisés basés sur les bibliothèques C / C ++ comme une tâche très difficile. Vous pouvez utiliser cette technologie pour introduire facilement presque toutes les bibliothèques C / C ++ dans Node.js. Si vous le souhaitez, vous pouvez également ajouter plus de fonctions au plug-in en fonction des besoins réels. Std :: String fournit beaucoup de méthodes et nous pouvons les utiliser comme matériel d'exercice.
Liens pratiques
Les amis intéressés peuvent vérifier les liens suivants pour plus de ressources et de détails liés au développement du plug-in Node.js, aux bibliothèques de boucle d'événements V8 et C.
• Documentation du plugin Node.js
• Documentation V8
• Libuv (C Library de boucle d'événements C), de GitHub
Anglais: http://code.tutsplus.com/tutorials/writing-nodejs-addons ---cms-21771