เป็นที่รู้กันว่าสำหรับทุกคนว่า Node.js นั้น Powerful ก็เพราะว่ามี Modules ให้เราใช้ไปแทบทุกอย่าง รวมถึงหลายๆคนอาจจะเคยเขียน Module ด้วย JavaScript ทั้งใช้เองและให้คนอื่นใช้
แต่วันนี้ผมจะมาแนะนำวิธีการเขียน Node.js module ด้วย C++ กัน
ก่อนอื่นในเมื่อเราเขียน Module ด้วย JavaScript ได้ทำไมต้องใช้ C++ มาดูข้อดีกันก่อนเลย
- System Access – ด้วย Native enviroment ทำให้ Module ที่เขียนด้วย C++ สามารถเข้าถึง API ของ System/OS ได้
- Performance – JavaScript นั้นทำงานด้วย Single Thread แต่ว่า Native นั้นสามารทำงานแบบ Multi Thread ได้
- Compiled Binary – JavaSciprt ถึงแม้จะมี Minify/Uglify แต่ก็พอจะ reverse engineer ได้แต่สำหรับ Native นั้นถึงแม้จะทำได้เหมือนกันแต่ก็ต้องมานั่ง Deassembly
เริ่มกันเลยครับ จริงๆแล้วผมก็ทำตาม https://nodejs.org/api/addons.html แต่!…ผมทำตามแล้วมันมีขั้นตอนเยอะและต้องใช้ Python ในการ Build อีก ผมเลยขอสรุปเองจากการลองแงะ Python scipt เพื่อลดความงงลง(หรือว่ายากขึ้น?)
- สร้าง Project C++ ใหม่จาก Visual Studio 2015
- เป็น DLL นะ
- ไปโหลด Node.js ไฟล์ headers และ node.lib มาครับที่
https://nodejs.org/download/release เลือกตาม version ของ Node ที่เราจะใช้ได้เลย เช่น v6.3.0
- Extract .gz แล้วก้ copy ไฟล์มาที่ Folder C++ Project ของเรา
ผมตั้งชื่อ folder เป็น
– include สำหรับ headers ไฟล์ที่เรา Extracted มา
– lib สำหรับเก็บ node.lib
- ที่นี้ก็ copy Source code นี้ไปที่ .cpp หลักครับ
// anurocha_node.cpp : Defines the exported functions for the DLL application. // #include "stdafx.h" #include "include/node/node.h" namespace demo { using v8::FunctionCallbackInfo; using v8::Isolate; using v8::Local; using v8::Object; using v8::String; using v8::Value; void SayHi(const FunctionCallbackInfo<Value>& args) { Isolate* isolate = args.GetIsolate(); args.GetReturnValue().Set(String::NewFromUtf8(isolate, "Hi - How are you doing?")); } void init(Local<Object> exports) { NODE_SET_METHOD(exports, "hello", SayHi); } NODE_MODULE(addon, init) } // namespace demo
- ลอง Build Project ดูครับ…เจ๊ง!
อ๊ะ!.. เราลืม Link ครับ - ไปเพิ่ม lib/node.lib ใน Linker ซะ
- Build อีกรอบ….เจ๊งเหมือนเดิม!!@#ไม่ต้องตกใจครับ….เป็นมุข..เรามี Lib ของ node.dll เป็น x64 ตามที่โหลดมา แต่เรากำลัง Compile แบบ x86 อยู่(ซึ่งเป็น Default Configuration ตอนสร้าง Project) ดังนั้นไปแก้ Project – Linker อีกรอบนึงครับ มั่นใจว่าแก้สำหรับ Platform x64 ด้วยนะครับ
- Build อีกทีจริงๆ ด้วย Target x64 นะครับ
- ถ้า Build ผ่านจะได้ไฟล์ .dll มาครับ
ให้เปลี่ยนชื่อเป็น anurocha.node แทน - สร้างไฟล์ app.js ง่ายๆมา มี Code แค่ 2 บรรทัด ที่ Folder เดียวกับ anurocha.node
const addon = require('./anurocha'); console.log(addon.hello());
- รัน “node app.js” ดูครับ…..แล้วความตื่นเต้นก็เกิดขึ้น!!!
สำเร็จแล้วกับ 12 ขั้นตอนที่ยาวนาน !!!!!
ลองมาดูรายละเอียดกันครับเกี่ยวกับขั้นตอนการทำงานของ JavsScript <–> C++
ซึ่งหัวใจสำคัญที่ทำให้ทั้ง 2 ภาษาคุยกันได้คือ V8 ที่เป็น JavaScript Engine เขียนด้วย C++ จาก Google นั่นเอง
- เวลาที่ dll ถูกโหลดด้วย JavaScript จาก require(); ตัว dll จะถูกเรียกครั้งแรกเพื่อทำการ Init ค่าต่างๆ
ในที่นี้เราทำการ export Fuction ที่ชื่อว่า hello ออกไป ซึ่ง function hello นั้นทำการ Map กับ Method ที่ชื่อว่า SayHivoid init(Local<Object> exports) { NODE_SET_METHOD(exports, "hello", SayHi); } NODE_MODULE(addon, init)
- เวลาที่ JavaScript เรียก addon.hello();
Code ฝั่ง C++ จะถูกเรียก Method ที่ชื่อว่า SayHi(); ทำให้มีการ return String object ที่มีค่า “Hi – How are you doing?” ออกมาให้ฝั่ง JavaScriptvoid SayHi(const FunctionCallbackInfo<Value>& args) { Isolate* isolate = args.GetIsolate(); args.GetReturnValue().Set(String::NewFromUtf8(isolate, "Hi - How are you doing?")); }
จากตัวอย่างนี้จะเห็นได้ว่าการเขียน Node.js Module ด้วย C++ นั้นอาจจะดูยุ่งยากซักนิดนึง แต่มันทำให้เราเขียน Logic ต่างๆด้วย C++ ได้ นั่นหมายความว่าถ้าเรารัน Node บน Windows เราก็สามารถเรียกใช้งาน Win32 API ต่างๆได้เช่น การเรียก Registry Key, ต่อ Socket, อ่านไฟล์บน HDD รวมถึงการทำงานร่วมกับสารพัด Library ของ C++ อย่างที่ทำได้เหมือนการเขียนโปรแกรมบน OS นั้นๆ….
LONG LIVE C++
ปล. Code ทั้ง Solution ดูได้จาก https://github.com/anurocha/node_cpp_addon ครับ
One thought on “สร้าง Node.js module แบบ Native ด้วย C++”