Maison > interface Web > js tutoriel > Utilisez C/C pour implémenter les modules Node.js (2)_node.js

Utilisez C/C pour implémenter les modules Node.js (2)_node.js

WBOY
Libérer: 2016-05-16 16:35:31
original
1130 Les gens l'ont consulté

Revoir le passé et apprendre le nouveau peut vous rendre heureux

Tout d'abord, n'oubliez pas ce manuel en ligne V8 - http://izs.me/v8-docs/main.html.

Vous souvenez-vous encore du fichier building.gyp de la dernière fois ?

Copier le code Le code est le suivant :

{
"cibles": [
{
"target_name": "module complémentaire",
"sources": [ "addon.cc" ]
>
]
>

Juste comme ça, si vous avez quelques fichiers *.cc supplémentaires, cela ressemblera à ceci :
"sources": [ "addon.cc", "monexemple.cc" ]

La dernière fois, nous avons séparé les deux étapes. En fait, la configuration et la compilation peuvent être mises ensemble :
$ node-gyp configurer build

Avez-vous fini de réviser ? sans? !

D’accord, continuons.

Table des matières

Paramètres de fonction

Maintenant, nous devons enfin parler des paramètres.

Imaginons qu'il existe une telle fonction add(a, b) qui représente l'ajout de a et b et le renvoi du résultat, alors écrivez d'abord le contour de la fonction :

Copier le code Le code est le suivant :

#include
en utilisant l'espace de noms v8 ;

Poignée Ajouter (const Arguments& args)
{
Portée HandleScope ;

//... C'est reparti !
>

Arguments

C'est le paramètre de la fonction. Jetons d’abord un coup d’œil à la référence officielle du manuel de la v8.
•int Longueur() const
•Opérateur Local[](int i) const

Le reste on s’en fout, ces deux-là sont importants ! L'un représente le nombre de paramètres passés dans la fonction et l'autre crochet est utilisé pour accéder au nième paramètre via l'index d'indice.

Par conséquent, nous pouvons à peu près comprendre les exigences ci-dessus car args.Length() est 2, args[0] représente a et args[1] représente b. Et nous devons déterminer que le type de ces deux nombres doit être Nombre.

Notez que l'opérateur d'index entre crochets renvoie une Local, qui est la classe de base de tous les types dans Node.js. Par conséquent, les paramètres transmis sont de type incertain et nous devons déterminer par nous-mêmes de quels paramètres il s’agit. Ceci est lié à certaines fonctions de ce type Value.

•IsArray()
•EstBooléen()
•EstDate()
•EstFonction()
•IsInt32()
•IsNativeError()
•EstNull()
•EstNuméro()
•IsRegExp()
•IsString()
•...

Je ne les listerai pas un par un, vous pouvez lire la documentation pour le reste. 。:.゚ヽ(*´∀`)ノ゚.:。

ThrowException

C'est une fonction que nous utiliserons plus tard. Les détails peuvent être trouvés dans la documentation v8.

Comme son nom l'indique, cela génère une erreur. Après avoir exécuté cette instruction, cela équivaut à exécuter une instruction throw() dans le fichier local Node.js. Par exemple :
ThrowException(Exception::TypeError(String::New("Mauvais nombre d'arguments")));

Cela équivaut à exécuter un Node.js :
throw new TypeError("Mauvais nombre d'arguments");

Non défini()

Cette fonction est également dans la documentation.

Plus précisément, il s'agit d'une valeur nulle, car certaines fonctions n'ont pas besoin de renvoyer de valeur spécifique, ou il n'y a pas de valeur de retour pour le moment, Undefined() doit être utilisé à la place.

Faisons-le, Saonian !

Après avoir compris les points ci-dessus, je pense que vous serez bientôt capable d'écrire la logique de a b. Je copierai le code du manuel officiel de Node.js et vous le donnerai pour que vous puissiez le parcourir :

Copier le code Le code est le suivant :

#include
en utilisant l'espace de noms v8 ;

Poignée Ajouter (const Arguments& args)
{
Portée HandleScope ;

// signifie que plus de 2 paramètres peuvent être transmis, mais en fait nous n'utilisons que les deux premiers
Si(args.Length() < 2)
{
​​​​ // erreur de lancement
         ThrowException(Exception::TypeError(String::New("Mauvais nombre d'arguments")));

// Renvoie la valeur nulle
          return scope.Close(Undefined());
>

// Si l'un des deux premiers paramètres n'est pas un nombre
Si(!args[0]->IsNumber() || !args[1]->IsNumber())
{
                 // Génère une erreur et renvoie une valeur nulle
         ThrowException(Exception::TypeError(String::New("Wrong arguments")));
          return scope.Close(Undefined());
>

// Veuillez vous référer à la documentation v8 pour plus de détails
// http://izs.me/v8-docs/classv8_1_1Value.html#a6eac2b07dced58f1761bbfd53bf0e366)
// Fonction `NumberValue`
Local num = Nombre::Nouveau(args[0]->NumberValue() args[1]->NumberValue());

return scope.Close(num);
>

La fonction est terminée !

Enfin, écrivez la fonction d’export à la fin et c’est OK.

Copier le code Le code est le suivant :

void Init (Handle exportations)
{
exports->Set(String::NewSymbol("add"),
FunctionTemplate::New(Add)->GetFunction());
>

NODE_MODULE(module complémentaire, Init)


Après l'avoir compilé, nous pouvons l'utiliser comme ceci :

Copier le code Le code est le suivant :
var addon = require('./build/Release/ module complémentaire') ;
console.log(addon.add(1, 1) "b");

Vous verrez un 2b ! ✧。٩(ˊᗜˋ)و✧*。

Fonction de rappel

Dans le dernier chapitre, nous n'avons parlé que de Hello World. Dans ce chapitre, grand-mère a fait une découverte consciente et a écrit une autre fonction de rappel.

Comme d'habitude, nous écrivons d'abord le framework :

Copier le code Le code est le suivant :

#include
en utilisant l'espace de noms v8 ;

Handle RunCallback (const Arguments& args)
{
Portée HandleScope ;

// ... crépitement crépitement

return scope.Close(Undefined());
>

Ensuite nous avons décidé de l'utiliser comme ceci :
func(fonction(msg) {
console.log(msg);
});

Autrement dit, il transmettra un paramètre à la fonction de rappel. Nous imaginons qu'il s'agit d'une chaîne, puis nous pourrons la console.log().

Vous devez d'abord avoir une série de chaînes

Sans plus attendre, alimentons-le d'abord en chaîne, puis parlons-en. (√ζε:)

Mais nous devons faire de cette chaîne un type universel, car le code Node.js est faiblement typé.
Local::New(String::New("hello world"));

Quoi ? Vous me demandez ce qu'est Local ?

Alors laissez-moi en parler un peu, référez-vous-y ici et au document de référence V8.

Comme indiqué dans la documentation, Local hérite en fait de Handle. Je me souviens que Handle

Alors parlons du Local.


Il existe deux types de handle, Local Handle et Persistent Handle. Les types sont Local : Handle et Persistent : Handle respectivement. Le cycle de vie entre dans le champ d'application. Le cycle de vie de ce dernier est hors de portée et vous devez appeler manuellement Persistent :: Dispose pour terminer son cycle de vie. En d'autres termes, Local Handle équivaut à l'allocation d'objets en C sur la pile et Persistent Handle équivaut à l'allocation d'objets en C sur le tas.

Ensuite, vous devez avoir une série de tableaux de paramètres

Comment obtenir les paramètres de ligne de commande après avoir appelé C/C depuis la ligne de commande du terminal ?

Copier le code Le code est le suivant :

#include

void main(int argc, char* argv[])
{
// ...
>

Au fait, argc est ici le nombre de paramètres de ligne de commande, et argv[] est chaque paramètre. En appelant ensuite la fonction de rappel de Node.js, la v8 utilise également une méthode similaire :

Copier le code Le code est le suivant :
V8EXPORT Local Objet>recv,
int argc,
Poignée argv[]
);

~~QAQ est bloqué dans Handle ! ! Je continuerai à écrire demain. ~~

Eh bien, une nouvelle journée a commencé et je me sens pleine de force. (∩^o^)⊃━☆゚.*・。

Après l'avoir vérifié sous de nombreux aspects (SegmentFault, StackOverflow et un groupe KouKou), j'ai finalement résolu la signification des trois paramètres de la fonction ci-dessus.

Je ne dirai pas grand-chose sur les deux paramètres suivants. L'un est le nombre de paramètres et l'autre est un tableau de paramètres. Quant au premier paramètre Handle, l'explication de StackOverflow est la suivante :


C'est la même chose que d'appliquer en JS. En JS, vous le faites
.

Copier le code Le code est le suivant :

var contexte = ...;
cb.apply(context, [ ...args...]);

L'objet passé comme premier argument devient ceci 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/comprendre-javascript-this/

——Extrait de StackOverflow

En bref, sa fonction est de spécifier le pointeur this de la fonction appelée. L'utilisation de cet appel est similaire à bind(), call() et apply() en JavaScript.

Ce que nous devons donc faire est de construire d'abord la table des paramètres, puis de transmettre la fonction Call pour exécution.

La première étape consiste à afficher la fonction de conversion, car il s'agit à l'origine d'un type Objet :
Local cb = Local::Cast(args[0]);

La deuxième étape consiste à créer une table de paramètres (array) :
Local argv[argc] = { Local::New(String::New("hello world")) };

Série de fonctions de dernier appel

Appelez cb et passez les paramètres dans :
cb->Call(Context::GetCurrent()->Global(), 1, argv);

Le premier paramètre ici, Context::GetCurrent()->Global(), signifie obtenir le contexte global comme celui de la fonction ; le deuxième paramètre est le numéro dans la table des paramètres (après tout, bien que Node.js Le tableau a un attribut de longueur, mais le système ne connaît pas en fait la longueur du tableau en C, et vous devez transmettre vous-même un nombre pour indiquer la longueur du tableau ; le dernier paramètre est la table de paramètres que nous venons de créer) ; .

Série de documents finaux du chapitre final

Je pense que tout le monde connaît déjà cette étape, qui consiste à écrire la fonction, puis à la mettre dans la fonction exportée, et enfin à la déclarer.

Je vais simplement publier le code directement, ou vous pouvez accéder directement à la documentation Node.js.

Copier le code Le code est le suivant :

#include
en utilisant l'espace de noms v8 ;

Handle RunCallback (const Arguments& args)
{
Portée HandleScope ;
Local cb = Local::Cast(args[0]);
const argc non signé = 1;
Local argv[argc] = { Local::New(String::New("hello world")) };
cb->Call(Context::GetCurrent()->Global(), argc, argv);

return scope.Close(Undefined());
>

void Init (exports Handle, module Handle)
{
Module->Set(String::NewSymbol("exports"),
FunctionTemplate::New(RunCallback)->GetFunction());
>

NODE_MODULE(module complémentaire, Init)

Bravo ! Faites simplement les dernières étapes restantes vous-même. Quant à l’appel de cette fonction en JS, je l’ai déjà mentionné.

Extra

Eh bien, j'ai l'impression que mes notes d'étude deviennent de plus en plus libres. S'il vous plaît, décomposez-les ~

.

Arrêtons-nous ici aujourd'hui. En train de rédiger des notes d'étude, j'ai encore eu des ennuis, comme la signification des paramètres de la fonction Call.

Si vous pensez que cette série de notes d'étude vous est toujours utile, venez me rejoindre pour vous amuser ~Σ>―(〃°ω°〃)♡→

Étiquettes associées:
source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal