مضيبة من n منذ فترة طويلة - باستخدام Node.js لإعادة بناء قاضي NBUT عبر الإنترنت ، بما في ذلك جانب التقييم ، يجب إعادة بناء. (أما بالنسبة عند اكتماله ، لا تهتم ، (/д ′)/~
باختصار ، ما سنفعله الآن هو استخدام C/C ++ لتنفيذ وحدات Node.js.
تحضير
إذا كنت ترغب في القيام بالأشياء بشكل جيد ، فيجب عليك أولاً أن تتصرف مثل عصابة وشحذ أدواتك.
عقدة GYP
تحتاج أولاً إلى وحدة Node-GYP.
في أي زاوية ، تنفيذ:
نسخة الكود كما يلي:
$ NPM تثبيت العقدة -ج -جي
بعد سلسلة من blahblahs ، قمت بتثبيتها.
بيثون
ثم تحتاج إلى بيئة بيثون.
انتقل إلى الموقع الرسمي واحصل على واحد.
ملاحظة: وفقًا لشاشة GitHub Node-GYP ، تأكد من التأكد من أن إصدار Python الخاص بك يتراوح بين 2.5.0 و 3.0.0.
بيئة التجميع
حسنًا ، أنا مجرد كسول ولا أكتبها بالتفصيل. يرجى الانتقال إلى Node-GYP لمشاهدة احتياجات المترجم. وجعل ضجة.
ابدء
سأخبرك عن مقدمة الموقع الرسمي Hello World.
مرحبا بالعالم
يرجى إعداد ملف C ++ ، على سبيل المثال ، يسمى ~~ sb.cc ~~ hello.cc.
ثم سنأخذ خطوة بخطوة ، أولاً إنشاء ملف الرأس وتحديد مساحة الاسم:
نسخة الكود كما يلي:
#include <node.h>
#include <v8.h>
باستخدام مساحة الاسم V8 ؛
الوظائف الرئيسية
بعد ذلك ، نكتب وظيفة هي قيمة إرجاعها معالجة <Value>.
نسخة الكود كما يلي:
تعامل مع <value> Hello (const arguments & args)
{
// ... كان جائعًا لكتاب
}
ثم سأقوم بتحليل هذه الأشياء تقريبًا:
التعامل مع <value>
يجب أن تكون صادقا في الحياة. أعلن مقدمًا أنني أشير إليها من هنا (fool).
يستخدم V8 نوع المقبض لاستضافة كائنات JavaScript. على غرار C ++ من std :: sharedpointer ، يتم تمرير الواجبات بين أنواع المقبض مباشرة مراجع الكائنات ، ولكن الفرق هو أن V8 يستخدم GC الخاص به لإدارة دورة حياة الكائن ، بدلاً من عدد المرجعية المستخدمة عادةً من قبل المؤشرات الذكية.
تحتوي أنواع javaScript على أنواع مخصصة مقابلة في C ++ ، مثل السلسلة ، عدد صحيح ، كائن ، تاريخ ، صفيف ، وما إلى ذلك ، وتلتزم بدقة بعلاقة الميراث في JavaScript. عند استخدام هذه الأنواع في C ++ ، يجب عليك استخدام استضافة المقبض لاستخدام GC لإدارة دورات حياتهم دون استخدام أكوام وأكوام أصلية.
هذه القيمة المزعومة ، والتي يمكن رؤيتها من مختلف علاقات الميراث في ملف الرأس v8.h من محرك V8 ، هي في الواقع الفئة الأساسية للكائنات المختلفة في JavaScript.
بعد فهم هذا ، يمكننا أن نفهم تقريبًا معنى بيان الوظيفة أعلاه ، مما يعني أننا نكتب وظيفة Hello ، التي تُرجع قيمة نوع غير مؤكد.
ملاحظة: يمكننا فقط إرجاع أنواع محددة ، وهي سلسلة ، عدد صحيح ، إلخ. ضمن استضافة المقبض.
الحجج
هذه هي المعلمة لتمريرها في هذه الوظيفة. نعلم جميعًا أنه في Node.js ، يكون عدد المعلمات عشوائيًا. عندما يتم تمرير هذه المعلمات إلى C ++ ، يتم تحويلها إلى كائن نوع الوسائط.
دعنا نتحدث عن الاستخدام المحدد لاحقًا. هنا نحتاج فقط إلى فهم ما هذا. (للحفاظ على سرية؟ لأن الأمثلة في وثيقة Node.js الرسمية تتم مناقشة بشكل منفصل. أنا أتحدث فقط عن أول مثال على Hello World (´థ౪థ) σ
أضف الطوب والبلاط
التالي نبدأ في المساهمة. فقط أبسط الجمل:
نسخة الكود كما يلي:
تعامل مع <value> Hello (const arguments & args)
{
نطاق handlescope.
Return Scope.Close (String :: New ("World")) ؛
}
ماذا تعني هاتان الجملتان؟ المعنى العام هو إعادة سلسلة "عالم" في Node.js.
handlescope
نفس المرجع من هنا.
تختلف دورة حياة المقبض عن تلك الموجودة في المؤشرات الذكية C ++. لا ينجو في نطاق دلالات C ++ (أي الجزء المحاط بـ {}) ، ولكن يجب تحديده يدويًا من خلال HandlesCope. لا يمكن تخصيص handlescope إلا على المكدس. بعد إعلان كائن HandlesCope ، يتم إدارة المقبض الذي تم إنشاؤه لاحقًا بواسطة HandlesCope. بعد تدمير كائن HandlesCope ، سيتم تحديد المقبض الذي تتم إدارته بواسطة GC.
لذلك ، علينا أن نعلن هذا النطاق عندما نحتاج إلى إدارة دورة حياتها. حسنًا ، فلماذا لا يتم كتابة رمزنا مثل هذا؟
نسخة الكود كما يلي:
تعامل مع <value> Hello (const arguments & args)
{
نطاق handlescope.
String Return :: New ("World") ؛
}
لأنه عند عودة الوظيفة ، سيتم تدمير النطاق وسيتم إعادة تدوير المقابض التي تديرها ، لذلك ستصبح هذه السلسلة بلا معنى.
توصل V8 إلى فكرة سحرية - وظيفة HandlesCope :: Close (مقبض <T> القيمة)! الغرض من هذه الوظيفة هو إغلاق النطاق وتسليم المعلمات داخل إدارة النطاق السابق ، أي النطاق قبل إدخال هذه الوظيفة.
لذلك لدينا الكود السابق Scope.Close (String :: New ("World")) ؛.
سلسلة :: جديدة
تتوافق فئة السلسلة مع فئة السلسلة الأصلية في Node.js. ورثت من فئة القيمة. وبالمثل ، هناك:
• صفيف
•عدد صحيح
• منطقية
•هدف
•تاريخ
•رقم
•وظيفة
• ...
بعض هذه الأشياء ورثت من القيمة ، في حين أن البعض الآخر ورث من الثانوية. لن نقوم بالكثير من الأبحاث هنا. يمكنك إلقاء نظرة على رمز V8 (على الأقل ملف الرأس) أو إلقاء نظرة على هذا الدليل.
وماذا عن هذا الجديد؟ يمكنك رؤيته هنا. إنه لإنشاء كائن سلسلة جديد.
في هذه المرحلة ، انتهينا من تحليل هذه الوظيفة الرئيسية.
كائنات التصدير
دعونا نراجعه. إذا تم كتابته في node.js ، كيف يمكننا تصدير وظائف أو كائنات؟
نسخة الكود كما يلي:
Exports.hello = function () {}
لذا ، كيف يمكننا القيام بذلك في C ++؟
تهيئة الوظيفة
أولاً ، دعنا نكتب وظيفة تهيئة:
نسخة الكود كما يلي:
void init (مقبض <Object> الصادرات)
{
// ... أنا جائع للكتابة عن أختك! #゚ Å ゚) ⊂ち☆)) ゚ д ゚) ・∵
}
هذا هو الحمار سلحفاة! لا يهم ما إذا كان اسم الوظيفة أو شيء ما ، ولكن يجب أن تكون المعلمة التي تم تمريرها مقبضًا <Object> ، مما يعني أننا سنقوم بتصدير الأشياء من هذا المنتج أدناه.
ثم ، نكتب الشيء المصدر هنا:
نسخة الكود كما يلي:
void init (مقبض <Object> الصادرات)
{
صادرات-> تعيين (String :: Newsymbol ("Hello") ،
functionTemplate :: New (Hello)-> getFunction ()) ؛
}
المعنى العام هو إضافة حقل يسمى Hello إلى كائن التصدير هذا ، والشيء المقابل هو وظيفة ، وهذه الوظيفة هي وظيفة Hello العزيزة.
لكتابة نقطة بسيطة في الرمز الزائف:
نسخة الكود كما يلي:
void init (مقبض <Object> الصادرات)
{
orports.set ("Hello" ، وظيفة مرحبًا) ؛
}
تم العمل!
(لقد انتهت أختك! اخرس ('д'⊂☡☆)) д´)
تصدير حقيقي
هذه هي الخطوة الأخيرة ، وسنعلن أخيرًا أن هذا هو مدخل التصدير ، لذلك نضيف هذا السطر في نهاية الرمز:
node_module (مرحبًا ، init)
هل أخذت ني؟ ! ما هذا؟
لا تقلق ، هذا node_module هو ماكرو ، مما يعني أننا نستخدم وظيفة التهيئة init لتصدير الأشياء المراد تصديرها إلى Hello. إذن من أين يأتي هذا مرحبا؟
يأتي من اسم الملف! نعم ، نعم ، إنه يأتي من اسم الملف. لا تحتاج إلى إعلان ذلك مسبقًا ، ولا داعي للقلق بشأن عدم القدرة على استخدامه. باختصار ، ما هو اسم الملف الثنائي المترجم النهائي؟ سوف تملأ Hello هنا ، وبالطبع عليك إزالة اسم لاحقة.
انظر الوثائق الرسمية للحصول على التفاصيل.
لاحظ أن جميع الإضافات يجب أن تصدر وظيفة التهيئة:
نسخة الكود كما يلي:
تهيئة باطلة (مقبض <Object> الصادرات) ؛
node_module (module_name ، تهيئة)
لا يوجد نصف كولون بعد node_module لأنها ليست وظيفة (انظر node.h).
يحتاج Module_Name إلى مطابقة اسم ملف الثنائي النهائي (ناقص لاحقة .node).
ترجمة (๑ • ́ ₃ • ̀๑)
تعال ، دعنا نتجمع معًا!
دعنا ننشئ ملف أرشيف جديد مشابه لـ Makefile - binding.gyp.
وأضف الرمز مثل هذا:
نسخة الكود كما يلي:
{
"الأهداف": [
{
"Target_Name": "مرحبًا" ،
"المصادر": ["Hello.cc"]
}
]
}
لماذا تكتب هذا؟ يمكنك الرجوع إلى الوثائق الرسمية لـ Node-GYP.
تكوين
بعد أن يكون الملف جاهزًا ، نحتاج إلى تنفيذ هذا الأمر في هذا الدليل:
نسخة الكود كما يلي:
$ node-gyp تكوين
إذا كان كل شيء على ما يرام ، فيجب إنشاء دليل بناء ، ثم هناك ملفات ذات صلة في الداخل ، وربما M $ Visual Studio VCXProj ، وما إلى ذلك ، أو ربما Makefile ، اعتمادًا على النظام الأساسي.
يبني
بعد إنشاء Makefile ، نبدأ في البناء وتجميع:
$ node-gyp build
فقط عندما يتم تجميع كل شيء ، سيتم اعتبار أن المهمة الحقيقية قد اكتملت! إذا كنت لا تصدق ذلك ، فاذهب وتحقق من دليل الإنشاء/الإصدار. هل يوجد ملف hello.node أدناه؟ هذا صحيح ، هذا هو الصابون الذي يريد C ++ التقاط Node.js لاحقًا!
دعونا نحصل على الأساسيات! العقدة (✿゚゚) ノ c ++
نقوم بإنشاء ملف جديد jianfeizao.js في الدليل الآن:
نسخة الكود كما يلي:
var addon = require ("./ build/release/hello") ؛
console.log (addon.hello ()) ؛
رؤيته أم لا! رؤيته أم لا! يخرج! نتيجة node.js و c ++ الحصول على الأساسيات! هذا addon.hello () هو المقبض <Value> Hello (const alcessions & args) كتبناه في رمز C ++ من قبل ، وقد نخرجنا الآن القيمة التي تُرجعها.
استحم واذهب إلى الفراش ، والقسم التالي أعمق
لقد تأخرت ، لذلك سأنتهي في النهاية إلى الكتابة اليوم. حتى الآن ، يمكن للجميع الخروج بامتداد Hello World C ++ الأساسي. في المرة القادمة التي أكتبها ، لا أعرف متى ستكون المرة القادمة.
(مهلا ، مهلا ، كيف يمكن أن يكون السيد غير مسؤول للغاية! (O ゚ロ?) ┌┛ (ノ ´ω`) ノ