Réviser l'ancien et apprendre le nouveau, vous pouvez devenir mouillé
Tout d'abord, n'oubliez pas ce manuel en ligne de V8 - http://izs.me/v8-docs/main.html.
Rappelez-vous le dernier fichier Building.gyp?
La copie de code est la suivante:
{
"cibles": [
{
"cible_name": "addon",
"Sources": ["addon.cc"]
}
]]
}
Juste comme ça, apprenez d'un exemple et apprenez-en. Si vous avez plus de fichiers * .cc, ce sera comme ceci:
"Sources": ["addon.cc", "myExample.cc"]
La dernière fois que nous avons séparé les deux étapes, et en fait, la configuration et la compilation peuvent être assemblées:
$ Node-Gyp Configure Build
Avez-vous fini de réviser? sans? !
Ok, alors continuons.
Table des matières
Paramètres de fonction
Maintenant, nous allons enfin parler des paramètres.
Imaginons qu'il existe une fonction ajouter (a, b) qui représente l'ajout de A et B pour retourner le résultat, alors écrivez d'abord le cadre extérieur de la fonction:
La copie de code est la suivante:
#include <node.h>
Utilisation de l'espace de noms v8;
Manipuler <value> add (construts et arguments et args)
{
Porce de capuche;
// ... reviens!
}
Arguments
Ceci est le paramètre de la fonction. Jetons un coup d'œil à la référence manuelle officielle de V8 en premier.
• int le long () const
• Opérateur <value> local [] (int i) const
Nous ne nous soucions pas des autres, ces deux-là sont très importants! L'un représente le nombre de paramètres passés dans la fonction, et l'autre est les supports qui accèdent au Nth Paramètre via l'index des indices.
Ainsi, en ce qui concerne les exigences ci-dessus, nous pouvons à peu près comprendre que Args.Length () est 2, Args [0] représente A et Args [1] représente b. Et nous devons juger que le type de ces deux nombres doit être le nombre.
Je ne suis pas sûr, l'opérateur d'index dans le support renvoie le résultat d'un <value> local, qui est la classe de base de tous les types de node.js. Par conséquent, si les paramètres transmis sont de type variable, nous devons juger de quels paramètres il s'agit. Ceci est lié à certaines fonctions de ce type de valeur.
• isArray ()
• Isboolean ()
• isDate ()
• isFunction ()
• isInt32 ()
• isNativeError ()
• isNull ()
• isNumber ()
• IsRegexp ()
• isstring ()
• ...
Je ne les énumérerai pas tous, je lis le reste par moi-même. 。:. ゚ (* ´∀`) ノ゚ .:。
ThrowException
Ceci est une fonction que nous utiliserons plus tard. Plus précisément, il peut être trouvé dans la documentation V8.
Comme son nom l'indique, il lance une erreur. Après avoir exécuté cette instruction, il équivaut à exécuter une instruction Throw () dans le fichier Node.js local. Par exemple:
ThrowException (exception :: typeError (string :: new ("mauvais nombre d'arguments")));
Il équivaut à exécuter un nœud.js:
Jetez un nouveau type Eerror ("mauvais nombre d'arguments");
Indéfini()
Cette fonction est également dans le document.
Plus précisément, il s'agit d'une valeur nulle, car certaines fonctions n'ont pas besoin de renvoyer une valeur spécifique ou de ne pas renvoyer de valeur. À l'heure actuelle, Undefined () doit être utilisé à la place.
Agissez!
Après avoir compris les points ci-dessus, je crois que vous pourrez bientôt écrire la logique de A + B. Je copierai le code du manuel officiel de Node.js et le lirai pour vous. Ce sera fait:
La copie de code est la suivante:
#include <node.h>
Utilisation de l'espace de noms v8;
Manipuler <value> add (construts et arguments et args)
{
Porce de capuche;
// Cela signifie que plus de 2 paramètres peuvent être passés, mais en fait nous n'utilisons que les deux premiers
if (args.length () <2)
{
// lance une erreur
ThrowException (exception :: typeError (string :: new ("mauvais nombre d'arguments")));
// Renvoie la valeur vide
return scope.close (undefined ());
}
// Si l'un des deux premiers paramètres n'est pas un nombre
if (! args [0] -> isNumber () ||! args [1] -> isNumber ())
{
// lance une erreur et renvoie une valeur nulle
ThrowException (exception :: typeError (string :: new ("mauvais arguments")));
return scope.close (undefined ());
}
// Pour plus de détails, veuillez vous référer à la documentation V8
// http://izs.me/v8-docs/classv8_1_1value.html#a6eac2b07dced58f1761bbfd53bf0e366)
// Fonction «NumberValue»
Local <Nom> num = Number :: new (args [0] -> NumberValue () + Args [1] -> NumberValue ());
return scope.close (num);
}
La fonction est terminée!
Enfin, écrivez la fonction d'exportation à la fin et ce sera OK.
La copie de code est la suivante:
void init (manche <objet> exportations)
{
Exports-> set (string :: newsymbol ("add"),
FunctionTemplate :: new (add) -> getFunction ());
}
Node_module (addon, init)
Après avoir compilé, nous pouvons l'utiliser comme ceci:
La copie de code est la suivante: var addon = require ('./ build / release / addon');
console.log (addon.add (1, 1) + "b");
Vous verrez un 2B! ✧。٩ (ᗜ) و✧ *.
Fonction de rappel
Dans le chapitre précédent, nous n'avons parlé que de Hello World. Dans ce chapitre, le maître grand-mère l'a découvert avec conscience et a écrit une fonction de rappel.
Pour la convention, écrivons d'abord un cadre:
La copie de code est la suivante:
#include <node.h>
Utilisation de l'espace de noms v8;
Manipuler <value> runCallback (construts et arguments)
{
Porce de capuche;
// ... cracky craqueliot craquelins craquelins craqueli
return scope.close (undefined ());
}
Ensuite, nous décidons comment il est utilisé comme ceci:
func (fonction (msg) {
console.log (msg);
});
Autrement dit, il passera un paramètre à la fonction de rappel, nous imaginons que c'est une chaîne, puis nous pouvons console.log () pour le voir.
Vous avez d'abord besoin d'une série de chaînes
Sans plus tarder, nourrissons d'abord une chaîne. (√ ζ ε :)
Mais nous devons faire cette chaîne de types génériques car le code Node.js est faible.
Local <value> :: new (String :: new ("Hello World"));
Quoi? Vous me demandez ce qu'est le <value> local?
Ensuite, j'en parlerai un peu, référer aux documents de référence d'ici et de V8.
Comme le montre la documentation, local <T> hérite en fait de Handle <T>, et je me souviens que le chapitre précédent avait déjà parlé de Handle <T>.
Alors voici le local.
Il existe deux types de poignée, la poignée locale et la poignée persistante, qui sont locales <T>: Handle <T> et persistant <T>: Handle <T>. Il n'y a pas de différence entre le premier et la poignée <T> et les deux cycles de survie sont dans la portée. Le cycle de vie de ce dernier est séparé de la portée, vous devez appeler manuellement persistant :: Disser pour mettre fin à son cycle de vie. En d'autres termes, la poignée locale est équivalente à l'allocation d'objets sur la pile sur C ++ 'et la poignée persistante est équivalente à C ++ allouant des objets sur le tas.
Ensuite, vous avez besoin d'une série de tableaux de paramètres
Comment obtenir des paramètres de ligne de commande après avoir appelé C / C ++ sur la ligne de commande du terminal?
La copie de code est la suivante:
#include <stdio.h>
void main (int argc, char * argv [])
{
// ...
}
Soit dit en passant, l'argc ici est le nombre de paramètres de ligne de commande, et Argv [] est les différents paramètres. Alors V8 utilise également une méthode similaire pour appeler la fonction de rappel de Node.js:
La copie de code est la suivante: v8Export local <value> v8 :: function :: complemente (manche <objet> recv,
int argc,
Manipuler <value> argv []
));
~~ QAQ est coincé dans Handle <Bject> Recv! ! ! Continuez à écrire demain. ~~
Eh bien, le nouveau jour commence et j'ai l'impression d'être plein de force. (∩ ^ o ^) ⊃━☆゚. * ・。。
Après avoir vérifié sous de nombreux aspects (segmentfault, stackOverflow et un groupe QQ), j'ai finalement résolu la signification des trois paramètres de la fonction ci-dessus.
Je ne parlerai pas des deux derniers paramètres, l'un est le nombre de paramètres, et l'autre est un tableau de paramètres. Quant à la première poignée de paramètre <objet> RECV, l'explication du frère Stackoverflow est la suivante:
C'est la même chose que celui appliqué dans JS. Dans JS, tu fais
La copie de code est la suivante:
var context = ...;
CB.Apply (contexte, [... args ...]);
L'objet passé lorsque le premier argument devient cela dans la portée de la fonction. Plus de documentation sur MDN. Si vous ne connaissez pas bien JS, vous pouvez en savoir plus sur JS ici: http://unschooled.org/2012/03/Understanding-javascript-this/
- extrait de StackOverflow
En bref, sa fonction est de spécifier ce pointeur vers la fonction appelée. L'utilisation de cet appel est similaire à Bind (), Call () et Apply () dans JavaScript.
Donc, ce que nous devons faire, c'est d'abord construire le tableau des paramètres, puis transmettre cette fonction d'appel pour son exécution.
La première étape consiste à afficher la fonction de conversion, car elle était à l'origine un type d'objet:
Local <Fonction> CB = local <Fonction> :: Cast (args [0]);
La deuxième étape consiste à créer une table de paramètres (array):
Local <value> argv [argc] = {local <value> :: new (String :: new ("Hello world"))};
L'appel final à la série de fonctions
Appelez CB et passez les paramètres dans:
CB-> Call (context :: getCurrent () -> global (), 1, argv);
Le premier paramètre ici contexte :: getCurrent () -> global () signifie obtenir cette fonction du contexte global; Le deuxième paramètre est le nombre dans la table des paramètres (après tout, bien que le tableau de Node.js ait un attribut de longueur, le système ne connaît en fait pas la longueur du tableau en C ++, et vous devez passer un nombre pour expliquer la longueur du tableau); Le dernier paramètre est le tableau des paramètres que nous venons d'établir.
Série de fichiers finaux finaux de chapitre
Je crois que tout le monde connaît déjà cette étape, écrivez simplement la fonction, puis mettez-la dans la fonction d'exportation et la déclare enfin.
Je vais simplement publier le code, ou aller simplement au document Node.js pour le lire.
La copie de code est la suivante:
#include <node.h>
Utilisation de l'espace de noms v8;
Manipuler <value> runCallback (construts et arguments)
{
Porce de capuche;
Local <Fonction> CB = local <Fonction> :: Cast (args [0]);
const non signé Argc = 1;
Local <value> argv [argc] = {local <value> :: new (String :: new ("Hello world"))};
CB-> Call (context :: getCurrent () -> global (), argc, argv);
return scope.close (undefined ());
}
void init (manche <objet> exportations, module de manche <objet>)
{
module-> set (string :: newsymbol ("exportations"),
FunctionTemplate :: new (runCallback) -> getFunction ());
}
Node_module (addon, init)
Bien joué! Allons vous-même les dernières étapes. Quant à appeler cette fonction dans JS, je l'ai déjà mentionné.
Supplémentaire
Eh bien, je pense que mes notes d'étude deviennent de plus en plus sans restriction et veulent les briser ~
Arrêtons-nous ici aujourd'hui. Au cours du processus d'écriture des notes d'étude, j'ai à nouveau augmenté ma posture, comme la signification du paramètre de la fonction d'appel.
Si vous pensez que cette série de notes d'étude vous est utile, venez passer un bon moment avec moi ~ σ> (〃 ° ω ° 〃) ♡ →