مراجعة القديم وتعلم الجديد ، يمكنك أن تصبح مبتلًا
بادئ ذي بدء ، يرجى تذكر هذا الدليل عبر الإنترنت من V8 - http://izs.me/v8-docs/main.html.
هل تتذكر آخر ملف Building.gyp؟
نسخة الكود كما يلي:
{
"الأهداف": [
{
"Target_Name": "Addon" ،
"المصادر": ["addon.cc"]
}
]
}
مثل هذا ، تعلم من مثال واحد وتعلم منه. إذا كان لديك المزيد من ملفات *.cc ، فسيكون الأمر هكذا:
"المصادر": ["addon.cc" ، "myexample.cc"]
آخر مرة افصلنا فيها الخطوتين ، وفي الواقع ، يمكن تجميع التكوين والتجميع معًا:
$ node-gyp تكوين بناء
هل انتهيت من المراجعة؟ بدون؟ !
حسنًا ، ثم دعنا نستمر.
جدول المحتويات
معلمات الوظيفة
الآن سنتحدث أخيرًا عن المعلمات.
دعونا نتخيل أن هناك وظيفة إضافة (أ ، ب) تمثل إضافة A و B لإرجاع النتيجة ، لذا اكتب الإطار الخارجي للوظيفة أولاً:
نسخة الكود كما يلي:
#include <node.h>
باستخدام مساحة الاسم V8 ؛
التعامل مع <value> إضافة (const almitures & args)
{
نطاق handlescope.
// ... تعال مرة أخرى!
}
الحجج
هذه هي معلمة الوظيفة. دعنا نلقي نظرة على المرجع اليدوي الرسمي لـ V8 أولاً.
• طول int () const
• مشغل <Suale> المحلي [] (int i) const
نحن لا نهتم بالآخرين ، وهذان الشخصان مهمان للغاية! يمثل أحدهم عدد المعلمات التي تم تمريرها في الوظيفة ، والآخر هو الأقواس التي تصل إلى المعلمة التاسعة من خلال فهرس المنشأة.
وذلك بالنسبة للمتطلبات المذكورة أعلاه ، يمكننا أن نفهم تقريبًا أن args.length () هو 2 ، تمثل args [0] a و args [1] ب. ويجب أن نحكم على أن نوع هذين الرقمين يجب أن يكون رقمًا.
لست متأكداً ، فإن مشغل الفهرس في القوس يرجع نتيجة <Sale> المحلية ، وهي الفئة الأساسية لجميع أنواع Node.js. لذلك ، إذا كانت المعلمات التي تم تمريرها من النوع المتغير ، فيجب علينا الحكم على المعلمات. يرتبط هذا ببعض الوظائف من نوع القيمة.
• isarray ()
• Isboolean ()
• isdate ()
• isfunction ()
• ISINT32 ()
• isNativeerror ()
• isnull ()
• isnumber ()
• ISREGEXP ()
• ISSTRING ()
• ...
لن أدرجهم جميعًا ، اقرأ الباقي بنفسي. 。 :. ゚ (*´∀`) ノ゚ .:。
رمي
هذه وظيفة سنستخدمها لاحقًا. على وجه التحديد ، يمكن العثور عليها في وثائق V8.
كما يوحي الاسم ، فإنه يرمي خطأ. بعد تنفيذ هذا البيان ، يعادل تنفيذ بيان رمي () في ملف Node.js المحلي. على سبيل المثال:
ThrowException (استثناء :: typeerror (String :: New ("عدد خاطئ من الوسائط"))) ؛
يعادل تنفيذ node.js:
رمي نوع جديد ("عدد خاطئ من الحجج") ؛
غير محدد ()
هذه الوظيفة هي أيضا في المستند.
على وجه التحديد ، إنها قيمة فارغة ، لأن بعض الوظائف لا تحتاج إلى إرجاع أي قيمة محددة ، أو لا تُرجع قيمة. في هذا الوقت ، يجب استخدام غير محدد () بدلاً من ذلك.
اتخاذ الإجراءات!
بعد فهم النقاط المذكورة أعلاه ، أعتقد أنك ستتمكن من كتابة منطق A + B قريبًا. سأقوم بنسخ كود الدليل الرسمي للعقدة. سيتم ذلك:
نسخة الكود كما يلي:
#include <node.h>
باستخدام مساحة الاسم V8 ؛
التعامل مع <value> إضافة (const almitures & args)
{
نطاق handlescope.
// هذا يعني أنه يمكن تمرير أكثر من 2 معلمتين ، ولكن في الواقع نستخدم فقط الأولين
if (args.length () <2)
{
// رمي خطأ
ThrowException (استثناء :: typeerror (String :: New ("عدد خاطئ من الوسائط"))) ؛
// إرجاع القيمة الفارغة
Return Scope.Close (undefined ()) ؛
}
// إذا كانت إحدى المعلمتين الأولين ليست رقمًا
if (! args [0]-> isNumber () ||! args [1]-> isNumber ())
{
// رمي خطأ وإرجاع قيمة فارغة
ThrowException (استثناء :: typeerror (String :: New ("الحجج الخاطئة"))) ؛
Return Scope.Close (undefined ()) ؛
}
// للحصول على التفاصيل ، يرجى الرجوع إلى وثائق V8
// http://izs.me/v8-docs/classv8_1_1value.html#a6eac2b07dced58f1761bbfd53bf0e366)
// `numbervalue` وظيفة
Local <number> num = number :: new (args [0]-> numberValue () + args [1]-> numberValue ()) ؛
Return Scope.Close (num) ؛
}
تتم الوظيفة!
أخيرًا ، اكتب وظيفة التصدير في النهاية وستكون على ما يرام.
نسخة الكود كما يلي:
void init (مقبض <Object> الصادرات)
{
صادرات-> تعيين (String :: Newsymbol ("Add") ،
functionTemplate :: new (add)-> getFunction ()) ؛
}
node_module (addon ، init)
بعد التجميع ، يمكننا استخدامه مثل هذا:
نسخة الكود كما يلي: var addon = require ('./ build/relex/addon') ؛
console.log (addon.add (1 ، 1) + "b") ؛
سترى 2 ب! ✧。٩ (ᗜ) و ✧*.
وظيفة رد الاتصال
في الفصل السابق ، تحدثنا فقط عن Hello World. في هذا الفصل ، اكتشفها سيد الجدة بالضمير وكتب وظيفة رد الاتصال.
للاتفاقية ، دعنا نكتب إطار عمل أولاً:
نسخة الكود كما يلي:
#include <node.h>
باستخدام مساحة الاسم V8 ؛
التعامل مع <value> RunCallback (const encuments & args)
{
نطاق handlescope.
// ... خرق خشب الخشخ
Return Scope.Close (undefined ()) ؛
}
ثم نقرر كيف يتم استخدامه مثل هذا:
func (وظيفة (msg) {
console.log (msg) ؛
}) ؛
أي أنه سيمرر معلمة إلى وظيفة رد الاتصال ، ونحن نتخيل أنها سلسلة ، وبعد ذلك يمكننا وحدة التحكم. log () لرؤيتها.
أولاً ، تحتاج إلى سلسلة سلسلة
بدون مزيد من اللغط ، دعنا نطعمها سلسلة أولاً. (√ ζ ε :)
لكن علينا أن نجعل هذه السلسلة من الأنواع العامة لأن رمز Node.js ضعيف.
Local <value> :: New (String :: New ("Hello World")) ؛
ماذا؟ تسألني ما هو <SALITY>؟
ثم سأتحدث عن ذلك قليلاً ، والرجوع إلى المستندات المرجعية من هنا و V8.
كما يظهر الوثائق ، يرث <T> المحلي بالفعل من المقبض <T> ، وأتذكر أن الفصل السابق قد تحدث بالفعل عن مقبض <T>.
ثم هنا هو المحلي.
هناك نوعان من المقبض والمقبض المحلي والمقبض المستمر ، وهما محليان <T>: المقبض <T> ومستمر <T>: Handle <T>. لا يوجد فرق بين السابق والمقبض <T> وكلا من دورات البقاء على قيد الحياة في نطاق. يتم فصل دورة حياة الأخيرة عن النطاق ، فأنت بحاجة إلى استدعاء يدويًا :: التصرف لإنهاء دورة حياتها. بمعنى آخر ، المقبض المحلي يعادل تخصيص الكائنات على المكدس على C ++ `والمقبض المستمر يعادل C ++ تخصيص الكائنات على الكومة.
ثم تحتاج إلى سلسلة جدول المعلمات
كيفية الحصول على معلمات سطر الأوامر بعد استدعاء C/C ++ على سطر الأوامر الطرفية؟
نسخة الكود كما يلي:
#include <stdio.h>
باطل رئيسي (int argc ، char* argv [])
{
// ...
}
بالمناسبة ، فإن ArgC هنا هو عدد معلمات سطر الأوامر ، و Argv [] هي المعلمات المختلفة. ثم يستخدم V8 أيضًا طريقة مماثلة لاستدعاء وظيفة الاتصال Node.js:
نسخة الكود كما يلي: v8export Local <Value> v8 :: function :: call (handle <bount> recv ،
int argc ،
معالجة <value> argv []
) ؛
~~ QAQ عالق في المقبض <Object> recv! ! ! استمر في الكتابة غدًا. ~~
حسنًا ، يبدأ اليوم الجديد وأشعر أنني مليء بالقوة. (∩^o^) ⊃━☆゚.*・。。
بعد التحقق من العديد من الجوانب (SegmentFault و Stackoverflow و QQ Group) ، قمت أخيرًا بحل معنى المعلمات الثلاثة للوظيفة أعلاه.
لن أتحدث عن المعلمتين الأخيرين ، أحدهما هو عدد المعلمات ، والآخر عبارة عن مجموعة من المعلمات. بالنسبة إلى مقبض المعلمة الأول <Object> recv ، فإن تفسير Stackoverflow Brother هو كما يلي:
هو نفسه كما هو مطبق في JS. في JS ، أنت تفعل
نسخة الكود كما يلي:
var context = ... ؛
cb.apply (السياق ، [... args ...]) ؛
تم تمرير الكائن كوسيطة أول يصبح هذا ضمن نطاق الوظيفة. المزيد من الوثائق على MDN. إذا كنت لا تعرف JS جيدًا ، فيمكنك قراءة المزيد حول JS هذا هنا: http://unschooled.org/2012/03/undershing-javascript-this/
- مقتطف من Stackoverflow
باختصار ، تتمثل وظيفتها في تحديد هذا المؤشر إلى الوظيفة المسمى. يشبه استخدام هذه المكالمة BIND () و CALL () و application () في JavaScript.
إذن ما يتعين علينا فعله هو إنشاء جدول المعلمات أولاً ، ثم تمرير وظيفة المكالمة هذه لتنفيذها.
الخطوة الأولى هي عرض وظيفة التحويل ، لأنها كانت في الأصل نوع كائن:
Local <function> cb = local <function> :: cast (args [0]) ؛
الخطوة الثانية هي إنشاء جدول معلمة (صفيف):
Local <Value> argv [argc] = {local <value> :: new (String :: New ("Hello World"))} ؛
الدعوة النهائية لسلسلة الوظائف
استدعاء CB وتمرير المعلمات في:
cb-> call (context :: getCurrent ()-> global () ، 1 ، argv) ؛
المعلمة الأولى هنا سياق :: getCurrent ()-> Global () تعني الحصول على هذه الوظيفة من السياق العالمي ؛ المعلمة الثانية هي الرقم في جدول المعلمة (بعد كل شيء ، على الرغم من أن صفيف Node.js له سمة طول ، إلا أن النظام لا يعرف في الواقع طول الصفيف في C ++ ، وعليك أن تمر في رقم لشرح طول المصفوفة) ؛ المعلمة الأخيرة هي جدول المعلمة الذي أنشأناه للتو.
سلسلة ملفات نهاية الفصل الأخيرة
أعتقد أن الجميع على دراية بهذه الخطوة بالفعل ، فقط اكتب الوظيفة ، ثم ضعها في وظيفة التصدير ، وأخيراً أعلن ذلك.
سأقوم فقط بنشر الرمز ، أو فقط انتقل إلى مستند Node.js لقراءته.
نسخة الكود كما يلي:
#include <node.h>
باستخدام مساحة الاسم V8 ؛
التعامل مع <value> RunCallback (const encuments & args)
{
نطاق handlescope.
Local <function> cb = local <function> :: cast (args [0]) ؛
const غير موقعة 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 (مقبض <Object> تصدير ، مقبض <Object> الوحدة النمطية)
{
الوحدة النمطية-> SET (String :: Newsymbol ("Exports") ،
functionTemplate :: new (runCallback)-> getFunction ()) ؛
}
node_module (addon ، init)
أحسنت! دعنا نذهب للخطوات الأخيرة بنفسك. أما بالنسبة لاستدعاء هذه الوظيفة في JS ، فقد ذكرتها من قبل.
إضافي
حسنًا ، أشعر أن ملاحظات دراستي أصبحت أكثر فأكثر وترغب في كسرها ~
دعنا نتوقف هنا اليوم. أثناء عملية كتابة ملاحظات الدراسة ، قمت بزيادة وضعي مرة أخرى ، مثل معنى المعلمة لوظيفة الاتصال.
إذا كنت تعتقد أن هذه السلسلة من ملاحظات الدراسة مفيدة لك ، تعال وقضي وقتًا ممتعًا معي σ> (〃 ° Ω ° 〃) ♡ →