Heim > Web-Frontend > js-Tutorial > Verwenden Sie C/C, um Node.js-Module (2)_node.js zu implementieren

Verwenden Sie C/C, um Node.js-Module (2)_node.js zu implementieren

WBOY
Freigeben: 2016-05-16 16:35:31
Original
1130 Leute haben es durchsucht

Das Vergangene Revue passieren zu lassen und Neues zu lernen, kann glücklich machen

Bitte denken Sie zunächst an dieses V8-Online-Handbuch – http://izs.me/v8-docs/main.html.

Erinnern Sie sich noch an die Datei „building.gyp“ vom letzten Mal?

Code kopieren Der Code lautet wie folgt:

{
„Ziele“: [
{
„target_name“: „addon“,
„Quellen“: [ „addon.cc“ ]
}
]
}

Einfach so, wenn Sie noch ein paar *.cc-Dateien haben, sieht es so aus:
„sources“: [ „addon.cc“, „myexample.cc“ ]

Beim letzten Mal haben wir die beiden Schritte getrennt. Tatsächlich können Konfiguration und Kompilierung zusammengefügt werden:
$ node-gyp configure build

Haben Sie die Bewertung abgeschlossen? ohne? !

Okay, lass uns weitermachen.

Inhaltsverzeichnis

Funktionsparameter

Jetzt müssen wir endlich über Parameter reden.

Stellen wir uns vor, dass es eine solche Funktion add(a, b) gibt, die das Addieren von a und b und die Rückgabe des Ergebnisses darstellt. Schreiben Sie also zunächst die Funktionsübersicht:

Code kopieren Der Code lautet wie folgt:

#include
unter Verwendung des Namespace v8;

Handle Add(const Arguments& args)
{
HandleScope-Bereich;

//... Es geht wieder los!
}

Argumente

Dies ist der Parameter der Funktion. Werfen wir zunächst einen Blick auf die offizielle Handbuchreferenz von v8.
•int Länge() const
•Lokaler-Operator[](int i) const

Der Rest ist uns egal, diese beiden sind wichtig! Eine stellt die Anzahl der an die Funktion übergebenen Parameter dar, und die andere Klammer wird verwendet, um über den Indexindex auf den n-ten Parameter zuzugreifen.

Daher können wir die oben genannten Anforderungen grob verstehen, da args.Length() 2 ist, args[0] a darstellt und args[1] b darstellt. Und wir müssen feststellen, dass der Typ dieser beiden Zahlen Zahl sein muss.

Beachten Sie, dass der Indexoperator in eckigen Klammern einen Local zurückgibt, der die Basisklasse aller Typen in Node.js ist. Daher sind die übergebenen Parameter von ungewissem Typ und wir müssen selbst bestimmen, um welche Parameter es sich handelt. Dies hängt mit einigen Funktionen dieses Werttyps zusammen.

•IsArray()
•IsBoolean()
•IsDate()
•IsFunction()
•IsInt32()
•IsNativeError()
•IsNull()
•IsNumber()
•IsRegExp()
•IsString()
•...

Ich werde sie nicht einzeln auflisten, den Rest können Sie in der Dokumentation lesen. 。:.゚ヽ(*´∀`)ノ゚.:。

ThrowException

Dies ist eine Funktion, die wir später verwenden werden. Details finden Sie in der v8-Dokumentation.

Wie der Name schon sagt, wird ein Fehler ausgegeben. Nach der Ausführung dieser Anweisung entspricht dies der Ausführung einer throw()-Anweisung in der lokalen Datei Node.js. Zum Beispiel:
ThrowException(Exception::TypeError(String::New("Falsche Anzahl von Argumenten")));

Es entspricht der Ausführung eines Node.js:
throw new TypeError("Falsche Anzahl von Argumenten");

Undefiniert()

Diese Funktion ist auch in der Dokumentation enthalten.

Konkret handelt es sich um einen Nullwert, da einige Funktionen keinen bestimmten Wert zurückgeben müssen oder es keinen Rückgabewert gibt. Stattdessen muss Undefiniert () verwendet werden.

Lass es uns tun, Saonian!

Nachdem Sie die oben genannten Punkte verstanden haben, glaube ich, dass Sie bald in der Lage sein werden, die Logik von a b zu schreiben. Ich werde den Code aus dem offiziellen Handbuch von Node.js kopieren und Ihnen zum Durchgehen geben:

Code kopieren Der Code lautet wie folgt:

#include
unter Verwendung des Namespace v8;

Handle Add(const Arguments& args)
{
HandleScope-Bereich;

// bedeutet, dass mehr als 2 Parameter übergeben werden können, aber tatsächlich verwenden wir nur die ersten beiden
If(args.Length() < 2)
{
​​​​ // Fehler auslösen
         ThrowException(Exception::TypeError(String::New("Falsche Anzahl von Argumenten")));

// Nullwert zurückgeben
          returnscope.Close(Undefiniert());
}

// Wenn einer der ersten beiden Parameter keine Zahl ist
If(!args[0]->IsNumber() || !args[1]->IsNumber())
{
                 // Einen Fehler auslösen und einen Nullwert zurückgeben
         ThrowException(Exception::TypeError(String::New("Wrong arguments")));
          returnscope.Close(Undefiniert());
}

// Weitere Informationen finden Sie in der Dokumentation zu Version 8
// http://izs.me/v8-docs/classv8_1_1Value.html#a6eac2b07dced58f1761bbfd53bf0e366)
// `NumberValue`-Funktion
Local num = Number::New(args[0]->NumberValue() args[1]->NumberValue());

returnscope.Close(num);
}

Die Funktion ist erledigt!

Schreiben Sie abschließend die Exportfunktion am Ende und es ist in Ordnung.

Code kopieren Der Code lautet wie folgt:

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

NODE_MODULE(addon, Init)


Nachdem Sie es kompiliert haben, können wir es wie folgt verwenden:

Code kopieren Der Code lautet wie folgt:
var addon = require('./build/Release/ addon') ;
console.log(addon.add(1, 1) "b");

Sie werden eine 2b sehen! ✧。٩(ˊᗜˋ)و✧*。

Rückruffunktion

Im letzten Kapitel haben wir nur über „Hallo Welt“ gesprochen. In diesem Kapitel hat Oma eine bewusste Entdeckung gemacht und eine weitere Rückruffunktion geschrieben.

Wie üblich schreiben wir zuerst das Framework:

Code kopieren Der Code lautet wie folgt:

#include
unter Verwendung des Namespace v8;

Handle RunCallback(const Arguments& args)
{
HandleScope-Bereich;

// ... knisternd knisternd

returnscope.Close(Undefiniert());
}

Dann haben wir beschlossen, es so zu verwenden:
func(function(msg) {
console.log(msg);
});

Das heißt, es wird ein Parameter an die Rückruffunktion übergeben. Wir stellen uns vor, dass es sich um einen String handelt, und können ihn dann mithilfe von console.log() ausgeben.

Zuerst benötigen Sie eine String-Serie

Lassen Sie uns ohne weitere Umschweife zuerst einen Faden ziehen und dann darüber reden. (√ ζ ε:)

Wir müssen diese Zeichenfolge jedoch zu einem universellen Typ machen, da der Node.js-Code schwach typisiert ist.
Local::New(String::New("hello world"));

Was? Sie fragen mich, was Local ist?

Dann lassen Sie mich ein wenig darüber sprechen, beziehen Sie sich hier darauf und auf das V8-Referenzdokument.

Wie in der Dokumentation gezeigt, erbt Local tatsächlich von Handle.

Dann lass uns über Lokal sprechen.


Es gibt zwei Arten von Handle: Local und Persistent. Der Lebenszyklus liegt im Rahmen. Der Lebenszyklus des letzteren liegt außerhalb des Gültigkeitsbereichs und Sie müssen Persistent::Dispose manuell aufrufen, um seinen Lebenszyklus zu beenden. Mit anderen Worten, Local Handle entspricht der Zuweisung von Objekten auf dem Stapel durch C und Persistent Handle entspricht der Zuweisung von Objekten auf dem Heap durch C.

Dann benötigen Sie eine Parametertabellenreihe

Wie erhalte ich die Befehlszeilenparameter, nachdem ich C/C über die Terminal-Befehlszeile aufgerufen habe?

Code kopieren Der Code lautet wie folgt:

#include

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

argc ist hier übrigens die Anzahl der Befehlszeilenparameter und argv[] ist jeder Parameter. Wenn Sie dann die Rückruffunktion von Node.js aufrufen, verwendet v8 ebenfalls eine ähnliche Methode:

Code kopieren Der Code lautet wie folgt:
V8EXPORT Local Objekt>recv ,
int argc,
Handle argv[]
);

~~QAQ steckt in Handle fest! ! ! Werde morgen weiter schreiben. ~~

Nun, ein neuer Tag hat begonnen und ich fühle mich voller Kraft. (∩^o^)⊃━☆゚.*・。

Nachdem ich es in vielen Aspekten überprüft habe (SegmentFault, StackOverflow und eine KouKou-Gruppe), habe ich endlich die Bedeutung der drei Parameter der obigen Funktion gelöst.

Zu den nächsten beiden Parametern werde ich nicht viel sagen. Einer ist die Anzahl der Parameter und der andere ist ein Array von Parametern. Für den ersten Parameter Handle lautet die Erklärung von StackOverflow wie folgt:


Es ist dasselbe wie in JS anwenden. In JS tun Sie es

Code kopieren Der Code lautet wie folgt:

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

Das als erstes Argument übergebene Objekt wird innerhalb des Funktionsumfangs zu diesem Objekt. Wenn Sie sich mit JS nicht gut auskennen, können Sie hier mehr über JS lesen: http://unschooled.org /2012/03/understanding-javascript-this/

——Auszug aus StackOverflow

Kurz gesagt besteht seine Funktion darin, den this-Zeiger der aufgerufenen Funktion anzugeben. Die Verwendung dieses Aufrufs ähnelt bind(), call() und apply() in JavaScript.

Was wir also tun müssen, ist, zuerst die Parametertabelle zu erstellen und dann die Call-Funktion zur Ausführung zu übergeben.

Der erste Schritt besteht darin, die Konvertierungsfunktion anzuzeigen, da es sich ursprünglich um einen Objekttyp handelt:
Local cb = Local::Cast(args[0]);

Der zweite Schritt besteht darin, eine Parametertabelle (Array) zu erstellen:
Local argv[argc] = { Local::New(String::New("hello world")) };

Letzte Aufruffunktionsreihe

Rufen Sie cb auf und übergeben Sie die Parameter:
cb->Call(Context::GetCurrent()->Global(), 1, argv);

Der erste Parameter hier, Context::GetCurrent()->Global(), bedeutet, dass der globale Kontext der Funktion abgerufen wird. Der zweite Parameter ist die Nummer in der Parametertabelle (schließlich ist Node.js Das Array hat ein Längenattribut, aber das System kennt die Länge des Arrays in C eigentlich nicht, und Sie müssen selbst eine Zahl übergeben, um die Länge des Arrays anzugeben. Der letzte Parameter ist die Parametertabelle, die wir gerade erstellt haben .

Abschlusskapitel, Abschlussdokumentenreihe

Ich glaube, jeder kennt diesen Schritt, der darin besteht, die Funktion zu schreiben, sie dann in die exportierte Funktion einzufügen und sie schließlich zu deklarieren.

Ich werde den Code einfach direkt veröffentlichen, oder Sie können direkt zur Node.js-Dokumentation gehen.

Code kopieren Der Code lautet wie folgt:

#include
unter Verwendung des Namespace v8;

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

returnscope.Close(Undefiniert());
}

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

NODE_MODULE(addon, Init)

Gut gemacht! Machen Sie die letzten verbleibenden Schritte einfach selbst. Den Aufruf dieser Funktion in JS habe ich bereits erwähnt.

Extra

Nun, ich habe das Gefühl, dass meine Lernnotizen immer hemmungsloser werden. Bitte teilen Sie es auf ~

Lassen Sie uns heute hier aufhören. Beim Schreiben von Studiennotizen bin ich erneut auf Probleme gestoßen, beispielsweise auf die Bedeutung der Parameter der Call-Funktion.

Wenn Sie der Meinung sind, dass diese Reihe von Studiennotizen immer noch hilfreich für Sie ist, kommen Sie und machen Sie mit bei dem Spaß~Σ>―(〃°ω°〃)♡→

Verwandte Etiketten:
Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage