ทำให้ App บน Windows เป็นสีขาว-ดำ

เนื่องจากว่าผมได้พยายามลองทำให้ Application บน Windows นั้นเปลี่ยนเป็นสีโทนขาว-ดำ เลยอยากจะแชร์สิ่งที่ได้ลองทำนะครับ (ถึงแม้ว่าผลของการ Implement นั้นยังไม่ถูกใจเท่าที่ควร)

ก่อนอื่นเลยผมขอเรียก app นี้ว่า Mourning App และเนื่องจากว่าต้องการทำสำหรับ Windows App ดังนั้นภาษาที่ผมใช้คือ C++ และ Win32 API ซึ่งตัว API ที่ใช้หลักๆคือ Magnification API ซึ่งเป็น Windows API ที่ปกติเอาไว้ทำพวก Tool ที่เป็นแว่นขยายต่างๆ

หลักการของ Mourning App ที่ผมทำมี 4 ขั้นตอน คือ

  1. หา Process ที่เราสนใจจะทำการ apply การทำภาพขาวดำก่อน

    API ที่ผมใช้ส่วนนี้คือ

    ::EnumProcesses ซึ่งทำให้เราได้จำนวน Process ที่กำลังรันอยู่ทั้งหมดมาพร้อมทั้ง Process ID ซึ่งเราจะใช้เอาไว้หาชื่อ Process ที่เราสนใจได้

  2. หา Window Handle (hwnd) ที่มันทำการแสดงผลอยู่ (visible) ของ Process นั้นๆ

    Code หลักๆที่ใช้ก็คือ  ::EnumWindows
    ซึ่งจากนั้นใน Callback ของ EnumWindowsProc นั้นจะได้ hwnd มาเรื่อยๆซึ่งผมจำการเช็ค

    if (!::IsWindow(hwnd) && !::IsWindowVisible(hwnd))
    return true;

  3. Render ทับตำแหน่ง application จริงๆด้วย Magnifier window พร้อมกับแปลงให้เป็นสีแบบ Gray Scale

    ส่วนนี้เป็นส่วนสำคัญที่สุด ซึ่งใช้ Magnification API โดยการสร้าง Window ด้วย Style : MS_CLIPAROUNDCURSOR

    m_hwndMag = CreateWindow(WC_MAGNIFIER, TEXT(“MagnifierWindow”),
    WS_CHILD | MS_CLIPAROUNDCURSOR | WS_VISIBLE

  4. ทำการ Refresh รูปบ่อยๆเพื่อให้ภาพเนียนที่สุดเวลา Application มีการ update หน้าจอ

    ส่วนนี้ไม่มีอะไรมากก็คือการตั้ง Timer เพื่อทำการ Refresh UI ครับแต่เราจะ Refresh เฉพาะ window ไม่ใช่ทั้งหน้าจอ Desktop

ตัวอย่างที่ได้ครับ

vscode
vscode in grayscale
chrome.png
Chrome เป็นสีเทา แต่ Edge ยังเป็นสีปกติ
ffx2.png
เกม FFX-2 ก็ทำให้ขาว-ดำ ได้นะครับ

ที่นี้มาดูผลที่ยังไม่น่าพอใจใน Implement ครั้งนี้ครับ

  1. ตัว render ภาพขาว-ดำนั้นเป็น Top Window ซึ่งทำให้ถ้ามี App ที่เปิดทับมันก็จะเป็นสีขาว-ดำด้วย
  2. ช้า เนื่องจากการ refresh นั้นบ่อยๆมีผลกับ Performance ทำให้ภาพมี delay บ้าง
  3. CPU ขึ้นตลอดเวลา 5% เนื่องจากต้อง query Process ตลอดเวลาในการเช็คว่ามี Window ของ Process ที่เราจะทำการ render ขาว-ดำ เปิดมาใหม่รึเปล่า

สุดท้ายนี้ ใครสนใจอยากดูตัวอย่างก็ Github เลยครับผม https://github.com/anurocha/mourning-win-app

เข้าสู่ C++ ยุคใหม่กับ Module System สำหรับ C++ 17/20

ไม่ยอมน้อยหน้าภาษา Modern เพราะหนึ่งใน Feature ที่มีการพูดถึงกันมากของมาตรฐานใหม่ของ C++ 17 ก็คือเรื่อง Module System (Link) ซึ่งเป็นแนวคิดทำให้ Library เป็น Module แบบจริงจัง โดยที่ทางกลุ่ม C++ Working Group ได้นำเสนอมานานแล้ว และมีแผนที่จะเอาเข้ามาเป็นส่วนหนึ่งของ C++ 17 แต่เหมือนว่าไม่น่าจะทัน C++ 17 แล้วครับ สรุปแล้วตอนนี้ Feature นี้อยู่ในขั้น Technical Specification ซึ่งน่าจะออกจริงใน C++ 20 (เลขข้างหลังเป็นเลขที่ เช่น 2017 หรือ 2020)

เป้าหมายของ Module System คือทำให้ C++ นั้นทำการ Compile ได้เร็วขึ้นและทำให้ Code นั้นมีการจัดการระดับ Component ได้ง่ายขึ้น เพราะปัจจุบัน #include นั้นใช้งานปนไปหมดทั้ง Headers, Inlines รวมทั้งบางทีมี Implemenation กันเลยทีเดียว

Microsoft นั้นได้ออก Preview สำหรับการทดลอง Module ใน Visual Studio 2015 Update 1+ มาลองดูกันเลยดีกว่า

ก่อนอื่นเลยครับ เนื่องจากว่า Visual Studio ในส่วนของ IDE นั้นยังไม่ Support ดังนั้นเราจะต้องทำการ Compile กับ Build ผ่าน Command Line นะครับ

สร้าง Module

ในการสร้าง Module นั้นให้เราสร้างไฟล์ใหม่มา ซึ่งโดยทั่วไปจะนิยมใช้ไฟล์ .ixx (ผมเดาว่ามาจาก Interface++)
เรามาสร้าง Module เอาไว้ Convert ค่าง่ายๆกัน

ไฟล์ converter.ixx

module converter;
export int CtoB(int x)
{
    return x + 543;
}

จาก code นี้จะเป็นการประกาศ Module ชื่อ converter ซึ่งมี function ‘CtoB’ ที่ทำการแปลง ค.ศ. ไป เป็น พ.ศ. ที่จะ export ออกไปให้ Code อื่นใช้

จากนั้นเราต้อง compile ด้วย commandline แบบนี้

cl /c /experimental:module converter.ixx

สิ่งที่ได้ก็คือไฟล์ converter.ifc กับ converter.obj

converter.png

เรียกใช้ Module

ที่นี้มาในส่วนของ Code หลักที่มี main entry point กันครับ ผมตั้งชื่อไฟล์ว่า main.cpp

ไฟล์ main.cpp

#include <iostream>
import converter;
int main()
{
 int year;
 std::cout << "Enter Year : ";
 std::cin >> year; 

 int bc = CtoB(year);
 std::cout << "Thai year is " << bc << std::endl;
 return 0;
}

Code ในส่วนนี้มีการเรียกใช้ Module ชื่อ ‘converter’ ด้วย keyword ที่ชื่อ import จากนั้นก็จะเรียกใช้ function ที่ชื่อ CtoB() ได้ทันทีเลยครับ

แน่นอนว่าเราต้อง compile ด้วย command line เช่นเคยโดยต้องระบุ converter.ifc เป็น parameter ของ module ที่จะเรียกใช้

cl /c /experimental:module /module:reference converter.ifc main.cpp

เมื่อรันเสร็จก็จะได้ main.obj มาครับ

main.png

ที่นี้จะเป็นว่าไม่มี .exe ให้เรา….สิ่งที่ต้องทำคือการสร้าง .exe ด้วย

link *.obj /OUT:main.exe

link.png

ทดสอบ

ลองรัน main.exe ที่ได้มาครับ ทำงานถูกต้องนะ 🙂

out.png

ลองด้วย Class

จากตัวอย่างข้างบนนั้นเป็นการสร้าง Module ด้วยการ export แค่ function แต่ถ้าเราอยากที่จะ  export Class ล่ะ เราก็ทำได้ครับ เช่น สร้าง Class  converter โดยมี method 2 ตัวให้เรียกใช้

module converter;
export namespace converterUtil
{
 class converter
 {
 public:
 int CtoB(int year)
 {
 return year + 543;
 }

 int CelsiusToFahrenheit(int c)
 {
 return (c * 1.8) + 32;
 }
 };
}

มาดูที่ main.cpp เราก็ทำการ import มาใช้และสร้าง Object ได้เลย เช่นใน ‘convt’ ตาม Code ด้านล่างนี้

#include <iostream>
import converter;
int main()
{
 converterUtil::converter convt;

 int year;
 std::cout << "Enter Year : ";
 std::cin >> year; 

 std::cout << "Thai year is " << convt.CtoB(year) << std::endl;

 int cel;
 std::cout << "Enter Temp in Celsius : ";
 std::cin >> cel; 
 std::cout << "Temp in Fahrenheit is " << convt.CelsiusToFahrenheit(cel) << std::endl;

 return 0;
}

ผลที่ได้ก็ Work ดีครับ!!

outex.png

สรุปแล้ว C++ Module น่าจะช่วยให้ C++ Developer ออกแบบและทำงานกับ Code ได้เป็นระเบียบเรียบร้อยขึ้น

และอีกอย่างคือจริงๆเท่าที่ผมลองในการสร้าง Module ถ้ามันมีใช้ header ตัวอื่นผมก็ยังทำให้มันเวิร์คไม่ได้นะ จึงต้องยกตัวอย่างแบบง่ายๆแบบนี้ครับ ซึ่งหวังว่าตัวจริงออกมาคงไม่วุ่นวายมากนะ

ณ. ตอนนี้เราก็มาเฝ้ารอ C++ 20 กันเลยกัย Module System!!

ปล. ดู Code ได้ที่ https://github.com/anurocha/cpp_module เลยครับผมอัพไว้ละ

JS++ อะไรกันนี่…

jspp_logo

เมื่อวันก่อนผมอ่าน Twitter แล้วมันก็เด้งบทความเกี่ยว JS++ มาให้อ่าน http://sdtimes.com/the-case-for-js-plus-plus/ ซึ่งเนื้อหาหลักๆที่ผมเข้าใจคือ ทางผู้พัฒนาต้องการอุดช่องว่างของ JavaScript ซึ่งหลักๆก็คือเรื่อง Type และ Object Oriented  ซึ่งโปรเจคแนวนี้ก็มีเยอะมากในวงการเช่น Dart หรือ TypeScript

ส่วน JS++ เองนั้นผู้พัฒนาคือ บริษัท Onux ซึ่งมี Official Site อยู่ที่ https://www.onux.com/jspp/
Platform ที่ทาง JS++ รองรับในตอนนี้คือ Windows กับ Linux เท่านั้น และในปัจจุบันนี้ อยู่ที่ Version 0.4.1 ซึ่งเป็น Early Access Preview อยู่

เมื่อ Install เสร็จก็จะได้ไฟล์ประมาณนี้

jspp_files.png

ลองเช็ค version ดูด้วย  js++ –version ก็ได้เป็น 0.4.1

jspp_ver.png

หลักการทำงานของ JS++ นั้นก็คือเราต้องเขียน Code ด้วย Systax ของ JS++ จากนั้นทำการ Compile ให้ออกมาเป็นไฟล์ .js ที่ Browser เข้าใจ

ที่นี้ลอง Hello World ง่ายๆ ด้วยการสร้างไฟล์ test.jspp

external document;

document.write("Hello World!");

ลอง Compile กันดูครับ

jspp_compiledไฟล์ที่ออกมาก็หน้าตาแบบนี้ครับ ซึ่งเป็นสิ่งที่ js เข้าใจ

// Compiled with JS++ v.0.4.1

!function(){document.write("Hello World!");}();

งั้นลองกับ Node.js หน่อยดีกว่า

import Convert;

external require;
external http = require("http");
external console;

string hostname = '127.0.0.1';
int port = 1337;

http.createServer(void(req, res) {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Hello World\n');
}).listen(port, hostname, void() {
console.log("Server running at http://" + hostname + ":" + Convert.toString(port) + "/");
});

Compile มาได้แบบนี้ (ดีจริง minify มาให้พร้อม)

// Compiled with JS++ v.0.4.1

!function(){var http=require("http");var hostname='127.0.0.1';var port=1337|0;http.createServer(function(req,res){res.writeHead(200,{'Content-Type':'text/plain'});res.end('Hello World\n');}).listen(port,hostname,function(){console.log("Server running at http://"+hostname+":"+(port+"")+"/");});}();

ลองรันดูก็ WORK ดีครับ

jspp_nodejs.png

ที่นี้ผมลองเอา Code จากหน้า Offical Page ที่มี Class มาลองอีกทีครับ ปรากฏว่า Compile Error เพราะหา Class ไม่เจอ…!@#$

jspp_cls.png

สรุป…ผมว่าสำหรับ Build นี้อาจจะยังไม่ถึงเวลาของ JS++ ในการใช้งานจริงครับ และผมก็คิดว่าทางตัวโปรเจคนี้ก็ยังความท้าทายในการเป็น Framework ที่ฮิตอยู่คือ

  1. ไม่เป็น Open Source
  2. ไม่มี บ.ยักษ์ใหญ่ช่วยหนุน
  3. ไม่มี Roadmap ชัดเจนสำหรับ Release ถัดๆไป

ผมคิดว่า ณ วันนี้ถ้าต้องการมองหาทางเลือกอื่นในการพัฒนา App หรือ Service โดยไม่ต้องใช้ JavaScript ตรงๆ ลองมอง TypeScript หรือ Dart ดีกว่าครับ…(ส่วนตัวตอนนี้ศึกษา TypeScript ครับ)

C++ ภาษานี้ก็ยัง Powerful อยู่เช่นเดิม

c_0

ถ้ามีคนมาถามผมว่าอยากเริ่มเขียนโปรแกรมจะเริ่มจากอะไร ผมก็จะตอบว่า ลองเขียน Java, C# ดูซึ่งเป็น OOP เต็มรูปแบบ มีเครื่องมือครบ และมี Syntax ที่ดีมาก หรือว่าพวกภาษา Script เช่น JavaScript, Python ก็ได้ เพราะจะได้เป็นการหัดคิดแบบเป็น Logic และฝึกแก้ปัญหา

แต่ถ้า ถามว่าอยากเขียนโปรแกรมให้เก่งแบบมองภาพรวมของ Software Architecture ออกจะต้องยังไง
ผมก็จะตอบว่าเขียน C++ ดู

ถึงแม้ว่าภาษา C จะเกิดมาตั้งแต่ปี ค.ศ. 1972 และ C++ มาตอน 1983 แต่ภาษานี้ก็ยังคงความนิยมและคุ้มค่าต่อการศึกษาครับ

เพราะ…C++

  1. เป็นภาษาที่อยู่ระดับเกือบระดับต่ำสุดเป็นรองแค่ Machine Code กับ Assembly ทำให้เราต้องรู้ว่า CPU มันทำงานยังไง
  2. เป็นภาษาที่ใกล้ชิดกับ OS ทำให้เราต้องรู้ว่า OS แต่ละแบบทำงานยังไงมีส่วนประกอบอะไรบ้างสำหรับโปรแกรมหรือ App ของเรา เช่นการจัดการ Process, Thread, File System, Memory, การทำงานระหว่าง Process (IPC)
  3. ไม่ค่อยมี Tool หรือ Function สำเร็จรูปมาให้แบบ Built-In ทำให้การที่เราจะเขียนอะไรง่ายๆ เช่นจะเขียนแปลง String ก็ต้องเขียนเองเยอะ ซึ่งข้อดีคือทำให้เข้าใน Logic/Algorithm ได้ดีขึ้น และมีนิสัยไม่ขี้เกียจที่จะลงแรงเองถึงแม้งานที่ดูเหมือนง่ายอาจจะต้องเขียนกัน 20-30 บรรทัด
  4. ไม่มี Memory Management ที่ฉลาดๆ เราที่จะเขียนก็ต้องฉลาดที่จะใช้เอง ต้องรู้ว่า Memory เก็บยังไงหลังจากที่ทำการ Allocate แล้ว และต้องรู้ว่าจะคืน Memory ให้ระบบตอนไหน
  5. เป็นภาษาที่ถูกต่อยอดไปเป็นภาษาสมัยใหม่หลายๆภาษา เช่น Java, C#, Objective-C, Swift, PHP, Python, Perl, Ruby, JavaScript และอื่นๆอีกมาก ทำให้เราสามารถไปศึกษาภาษาพวกนี้ได้เร็วขึ้น(จริงๆนะ)
    เปรียบเทียบกับทำให้เหมือนเรารู้ภาษาละตินซึ่งเป็นรากฐานของภาษาในยุโรปเกือบทั้งหมด!
  6. ทำให้รู้กระบวนการของการ Compile โปรแกรมตั้งแต่ เขียน Code ไปจนได้ไฟล์ Executable ออกมา
  7. เข้าใจการทำงานของ Framework หลายๆอย่างในปัจจุบัน เช่น OS, Web Browser, .NET Framework หรือ JVM รวมทั้ง Game Engine ต่างๆ และยังใช้เขียนต่อกับ Hardware ด้วย
  8. ส่วนมากจะเป็นสะพานเชื่อมการทำงานระหว่าง Technology เช่นเขียน .NET app ให้คุยกับ Web
  9. Performance ถึงแม้ว่าทุกวันนี้ CPU เราจะแรง แต่ถ้าต้องการรีด CPU ทุก clock cycle การใช้ C++ ก็ช่วยได้นะครับ
  10. Debug ได้ถึง Memory รวมทั้งสามารถ Deassembly Code มาดูเพื่อทำ Reverse Engineer ได้ ถ้าเราเก่งพอ :p
  11. เขียนได้หลาย Paradiam เช่น Imperative, Object-Oriented, Generic Programming (และทำให้ Code มั่วดีด้วยครับถ้าเขียนบนกันทุก Paradiam 555)
  12. ที่สำคัญ ภาษา C++ นั้นยังมีการพัฒนาอยู่เสมอซึ่ง version หลังๆก็คือ C++11/C++14 และที่กำลังจะมาคือ C++17 (เลขข้างหลังคือเลขปี ค.ศ.ที่จะออก) ซึ่งสิ่งที่เพิ่มเข้ามาทำให้เขียน Code ได้ง่ายขึ้น เช่นเดียวกับภาษายุคใหม่แหละครับ

 

C++ is still ROCK (as always)!

ปล.

  • บทความนี้ความเห็นส่วนตัวนะครับ 🙂
  • C++ เป็นภาษาแรกที่ผมอยากเขียนหลังจากที่ผมรู้จักคอมพิวเตอร์ ตอน ม.ปลาย (เพราะอยากเขียนเกม) แต่ไม่สำเร็จเพราะเข้าไม่ถึงผมเลยหนีไปเขียนเวป PHP, C#, Java ตอนเรียนมหาวิทยาลัย
  • C++ เป็นภาษาที่ใช้ในโปรเจคแรกของชีวิตการทำงาน Developer ของผม

Node.js ด้วยขุมพลัง Chakra ของ Microsoft

ตามคาดครับเจ้าใหญ่อย่าง Microsoft ก็เข้ามามีบทบาทในโลก Node.js หลังจากประกาศเป็นมิตรกับ Open Source วันนี้เรามาลองเล่น Node.js โดยที่รันด้วย ChakraCore ซึ่งเป็น Engine ที่รัน JavaScript ที่อยู่เบื้องหลัง Microsoft Edge (ผมชอบนะเปิด app เร็วดี :p ) แทนที่จะเป็น V8 ตาม version ปกติ

เริ่มจากไปดูใน node-chakracore เราก็พอจะได้ความว่า โปรเจคนี้เปิดตัวมา 6 เดือนแล้ว และมาถึงวันนี้ก็ยังอยู่ใน version ทดสอบอยู่นะครับ ซึ่ง Features หลักๆก็น่าจะพร้อมใช้งานระดับหนึ่ง

เนื่องจากผมขี้เกียจจะมา Build เองก็ไปโหลดตัว Prebuilt มาได้เลยจาก node-chakracore/releases เท่าๆที่ดูก็สามารถใช้งานได้บน Windows, ARM และ Linux (Mac หายไปไหน???)

ผมขอลอง Windows x64 ละกันครับ

หลังจาก Install แล้วตัว Node.js ก็น่าอยู่ที่ “C:\Program Files\nodejs (chakracore)” ซึ่งเป็น Path ปกติก็จะเห็นว่ามีไฟล์ ‘chakracore.dll’ เพิ่มเข้ามา

node_e_files.png
nodejs (chakracore) folder

ซึ่งถ้าเทียบกับ Node.js ปกติ จะเห็นว่า node.exe นั้นไฟล์ขนาด 16MB เพราะรวม V8 engine ไปด้วยในไฟล์เดียวกัน

node_v8_files.png
nodejs ปกติ

ลองเทส http server ง่ายๆก่อน

Code ข้างล่างเป็นการสร้าง Web Sever แบบพื้นฐานที่สามารถส่ง Hello.. กลับไปหน้าเวปได้

// app.js
let http = require(‘http’);

let server = http.createServer( (request, response)=> {
response.write(‘Hello…!’);
response.end();
});

server.listen(80);
console.log(“Server is listening”);

ก็รันได้ดีปกติครับ

node_e_run

 

Performance

ไหนๆก็ไหนๆมาลองดู Performance ดีกว่า เรามาวนลูปเล่นๆกัน “ล้าน” รอบ

console.time(‘test:’);
for(let i = 0; i < 1000000 ; ++i){
let x = Math.random();
}
console.timeEnd(‘test:’);

ลองรันไป 3 รอบ ก็ได้ค่าเฉลี่ยประมาณ 5ms!!

node_e_loop.pngลองรันกับ Node.js (V8) ปกติก็พบว่า…. 15ms ช้ากว่า Chakra เกือบ 3 เท่า…

node_v8_loop.png

ที่นี้เราลองเรียก fucntion หลายๆชั้นดีกว่า เพื่อดูว่าถ้ามี Function ใน Call Stack สัก 3 ชั้นผลจะเป็นยังไง

console.time(‘test:’);
for(let i = 0; i < 1000000 ; ++i){
let x = Math.random();
do1();
}
console.timeEnd(‘test:’);

function do1(){
do2();
}

function do2(){
do3();
}

function do3(){

}

Chakra จัดไป ~9.5ms

node_e_fn_loop.png

ส่วน V8 ก็ยังแถวๆ ~15.7ms

node_v8_fn.png

สรุปสำหรับ Performance ส่วนของ Chakra ก็ยังทำได้ดีกว่าระดับหนึ่ง ซึ่งก็สอดคล้องกับ Official Blog ใน https://blogs.windows.com/msedgedev/2016/06/22/javascript-performance-updates-anniversary-update/

 

สร้าง Node.js module แบบ Native ด้วย C++

node_cpp

เป็นที่รู้กันว่าสำหรับทุกคนว่า Node.js นั้น Powerful ก็เพราะว่ามี Modules ให้เราใช้ไปแทบทุกอย่าง รวมถึงหลายๆคนอาจจะเคยเขียน Module ด้วย JavaScript ทั้งใช้เองและให้คนอื่นใช้

แต่วันนี้ผมจะมาแนะนำวิธีการเขียน Node.js module ด้วย C++ กัน

ก่อนอื่นในเมื่อเราเขียน Module ด้วย JavaScript ได้ทำไมต้องใช้ C++ มาดูข้อดีกันก่อนเลย

  1. System Access – ด้วย Native enviroment ทำให้ Module ที่เขียนด้วย C++ สามารถเข้าถึง API ของ System/OS ได้
  2. Performance – JavaScript นั้นทำงานด้วย Single Thread แต่ว่า Native นั้นสามารทำงานแบบ Multi Thread ได้
  3. Compiled Binary – JavaSciprt ถึงแม้จะมี Minify/Uglify แต่ก็พอจะ reverse engineer ได้แต่สำหรับ Native นั้นถึงแม้จะทำได้เหมือนกันแต่ก็ต้องมานั่ง Deassembly

เริ่มกันเลยครับ จริงๆแล้วผมก็ทำตาม https://nodejs.org/api/addons.html  แต่!…ผมทำตามแล้วมันมีขั้นตอนเยอะและต้องใช้ Python ในการ Build อีก ผมเลยขอสรุปเองจากการลองแงะ Python scipt เพื่อลดความงงลง(หรือว่ายากขึ้น?)

  1. สร้าง Project C++ ใหม่จาก Visual Studio 2015
    newproj
  2. เป็น DLL นะ
    dllproj
  3. ไปโหลด Node.js ไฟล์ headers และ node.lib มาครับที่
    https://nodejs.org/download/release เลือกตาม version ของ Node ที่เราจะใช้ได้เลย เช่น v6.3.0
    download
  4. Extract .gz แล้วก้ copy ไฟล์มาที่ Folder C++ Project ของเรา
    ผมตั้งชื่อ folder เป็น
    – include สำหรับ headers ไฟล์ที่เรา Extracted มา
    – lib สำหรับเก็บ node.lib
    copy_dep
  5. ที่นี้ก็ 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
  6. ลอง Build Project ดูครับ…เจ๊ง!
    link_err
    อ๊ะ!.. เราลืม Link ครับ
  7. ไปเพิ่ม lib/node.lib ใน Linker ซะ
    linker
  8.  Build อีกรอบ….เจ๊งเหมือนเดิม!!@#ไม่ต้องตกใจครับ….เป็นมุข..เรามี Lib ของ node.dll เป็น x64 ตามที่โหลดมา แต่เรากำลัง Compile แบบ x86 อยู่(ซึ่งเป็น Default Configuration ตอนสร้าง Project) ดังนั้นไปแก้ Project – Linker อีกรอบนึงครับ มั่นใจว่าแก้สำหรับ Platform x64 ด้วยนะครับ
    linker64
  9.  Build อีกทีจริงๆ ด้วย Target x64 นะครับbuildx64
  10. ถ้า Build ผ่านจะได้ไฟล์ .dll มาครับ
    out
    ให้เปลี่ยนชื่อเป็น anurocha.node แทน
  11. สร้างไฟล์ app.js ง่ายๆมา มี Code แค่ 2 บรรทัด ที่ Folder เดียวกับ anurocha.node
    const addon = require('./anurocha');
    console.log(addon.hello());
  12. รัน “node app.js” ดูครับ…..แล้วความตื่นเต้นก็เกิดขึ้น!!!
    node_out

สำเร็จแล้วกับ 12 ขั้นตอนที่ยาวนาน !!!!!

ลองมาดูรายละเอียดกันครับเกี่ยวกับขั้นตอนการทำงานของ JavsScript <–> C++
ซึ่งหัวใจสำคัญที่ทำให้ทั้ง 2 ภาษาคุยกันได้คือ V8 ที่เป็น JavaScript Engine เขียนด้วย C++ จาก Google นั่นเอง

  1. เวลาที่ dll ถูกโหลดด้วย JavaScript จาก require(); ตัว dll จะถูกเรียกครั้งแรกเพื่อทำการ Init ค่าต่างๆ
    ในที่นี้เราทำการ export Fuction ที่ชื่อว่า hello ออกไป ซึ่ง function hello นั้นทำการ Map กับ Method ที่ชื่อว่า SayHi

    void init(Local<Object> exports) {
     NODE_SET_METHOD(exports, "hello", SayHi);
     }
    
     NODE_MODULE(addon, init)
  2. เวลาที่ JavaScript เรียก addon.hello();
    Code ฝั่ง C++ จะถูกเรียก Method ที่ชื่อว่า SayHi(); ทำให้มีการ return String object ที่มีค่า “Hi – How are you doing?” ออกมาให้ฝั่ง JavaScript

    void 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 ครับ

IDE หนึ่งในสิ่งพื้นฐานควรรู้ของ Developer

Developer คนไหนไม่รู้จัก IDE บ้าง? ถ้าคนๆนั้นเป็นคุณก็…..อ่านต่อเถอะครับ 🙂
ส่วนถ้ารู้แล้วก็ลองอ่านเล่นๆดูได้ครับ

IDE ย่อมากจาก Integrated Development Enviroment ซึ่งก็คือเครื่องมือที่ Developer ใช้ในการพัฒนา Software แบบครบวงจร เช่น Visual Studio, XCode, Netbean, Eclips, Xamarin และอื่นๆ

โดยความสามารถหลักๆ ของ IDE ผมขอแบ่งเป็น 4 อย่างใหญ่ๆละกัน

  1. Editor – เอาไว้เขียน Source Code รวมถึงพวก Syntax Hilight, Auto-Complete
  2. Compiler – เอาไว้ Build โปรแกรมจาก Code ไปเป็น Binary
  3. Debugger – เอาไว้ใช้ในการแก้หาวิธีในการแก้ Bug
  4. Tools – เครื่องมือช่วยต่างๆ เช่น Refactoring, จัดหน้าจอหรือ Visual Design, การทำ UML, ดู Database รวมถึงพวกทำ Static Code Analysis และการสร้าง Document จาก Code

มาถึงตรงนี้แล้วมีใครใช้ IDE ครบ 4 อย่างมั้ยครับ….จากประสบการณ์ของผมแล้วน้องๆ Developer  ส่วนใหญ่จะรู้จักมันในฐานะข้อ 1 และ 2 เท่านั้น

ซึ่งผมอยากแนะนำสำหรับคนที่ยังไม่ได้ลองใช้ความสามารถของ IDE ในการเป็น Debugger ควรจะหาเวลาไปเรียนรู้ไว้ครับ เพราะมันจะช่วยทำให้คุณแก้ Bug รวมถึงพัฒนา Feature ที่ซับซ้อนได้เร็วขึ้นจริงๆ

แต่ช้าก่อน…..ถ้าท่านที่สามารถทำงานกับโปรเจคขนาดใหญ่โดยไม่ต้องใช้ Debugger ได้ผมนับถือมากครับ แสดงว่า  Source Code น่าจะมี Unit Test ครบ 100% ซึ่งทำให้เจอBug ได้จาก Unit Test และไม่ต้องพึ่งการ Debug

นี่คือ Utopia of Software – Software ในอุดมคติเลย!

Final Fantasy X/X-2 HD Remaster กับ Windows architecture

พอดีได้ข่าวว่า Final Fantasy X ได้ทำการ Port มาลง PC ก็เลยลองเล่นดูครับ เพราะภาคนี้ผมเล่นตอน PS2 ได้ประมาณ 30-40% แล้วก็ไม่ได้เล่นต่อเนื่องจากติดทำ Project จบสมัยเรียน เลยขายเครื่องทิ้งไปเพราะกลัวเรียนไม่จบ 🙂

แต่ที่เขียนถึงวันนี้คงพูดถึงเรื่อง Windows architecture กันนิดหน่อย

สืบเนื่องมาจากว่า ผมเล่นเกมนี้ไปได้ประมาณไม่นานเช่น 10-20นาที โปรแกรมก็ Crash ซึ่งมาจากขั้นตอนที่ไม่แน่นอน หรือเรียกว่า Random Crash นั่นเอง

ซึ่งการ Crash ของ Application นั้นก็หมายถึงการที่โปรแกรมหยุดทำงานด้วยสาเหตุใดสาเหตุหนึ่งแล้วโปรแกรมก็เด้งออกอัตโนมัติทิ้งให้เราอึ้งไปหลายวิ..

As User

จากการที่เราเป็น End User ของเกมนี้ก็ แน่นอนครับ ติดปัญหาเราก็ต้องลองหาใน Google ดูก็ก่อนเลย ซึ่งก็พบว่ามีหลายๆคนเจอปัญหาเดียวกัน

http://steamcommunity.com/app/359870/discussions/0/364042063114641626/
http://steamcommunity.com/app/359870/discussions/0/364042262885080038/
http://steamcommunity.com/app/359870/discussions/0/364042262879682906/

ซึ่งผมลองทำตาม workaround ต่างๆแต่ก็ยังไม่สำเร็จ เล่นไปสักแป๊บนึงเกมก็เด้งออกมาอีกเช่นเคย

As Developer

แต่ด้วยความที่เราก็ Developer ผมก็ตัดสินใจลอง Investigate ปัญหานี้ดูด้วยตัวเอง

สิ่งแรกที่ผมเห็นคือเวลามัน Crash ตัวไฟล์ CoreDump.dmp จะถูกสร้างขึ้นมา

coredump.png

ลองเปิดด้วย Visual Studio เพื่อทำการ Analyze Dump ไฟล์ได้ข้อมูลน่าสนใจตามนี้

dumpinfo

  1. Process นี้เป็น x86 ก็คือ 32 Bits
  2. Crash ที่เกิดขึ้นมี Exception เกี่ยวกับ Virtual Address หรือ Virtual Memory นั่นเอง

พอรู้แบบนี้ผมก็ลองเปิด Process Explorer ดูเลยครับว่าเวลาเล่นเกมนี้ มันใช้ Memory ขนาดไหน ปรากฎว่า…

ชัดเจนครับแค่เปิดเกมมา Virtual Memory ก็1.9GB แล้ว

screen

memreach

นี่คือสาเหตุของปัญหานี้ครับ..เนื่องจากว่า เกม(Process) นี้ถูก Compile ด้วย 32 Bits ทำให้สามารถใช้งาน Memory Space ได้ 2^32 bytes หรือประมาณคร่าวๆได้ 4GB (4,000,000KB โดยประมาณ)

แต่เนื่องจาก Windows Architect นั้นได้ทำการแบ่ง Memory ไว้เป็น 2 ส่วนคือ Kernel space กับ Application space (User space) อย่างละ 2GB

ซึ่งง่ายๆก็คือ Applicatoin จะใช้ได้ 2GB เท่านั้น ทำให้ถ้าใช้เกินโปรแกรมก็จะ Crash (ถ้าจัดการไม่ดี)

วิธีแก้ปัญหา

Windows นั้นได้มี Feature ที่เรียกว่า Large Address Aware ซึ่งทำให้ Application สามารถใช้งาน Memory ได้มากกว่า 2GB นั่นเอง

Tool ตัวนี้คือ Editbin.exe ซึ่งติดตั้งมากับ Microsoft Visual Studio อยู่แล้วครับ

พิมพ์ไปเลยครับตามนนี้

editbin /largeaddressaware “D:\Games\Final Fantasy X\FFX.exe”

editbin.png

เราก็จะได้ FFX.exe ตัวใหม่ที่ทำการเปิด Feature Large Address Aware แล้ว และเมื่อลองทดสอบดู Process ของเกมนี้ก็สามารถใช้ Memory ได้เกิน 2GB แล้ว

final_mem

และสุดท้ายตั้งแต่ผมแก้มาก็เล่นได้ 4-5 ชั่วโมงได้ไม่เจออาการ Crash/Freeze อีกเลยครับ 🙂

 

English:

For english guys (if any), I found one potential workaround to solve the random crash/freeze issues on FFX HD Remaster on PC. I think the issue is around memory reach limit of 32 Bits process which is 2GB for application space(from totally 4GB  – kernel and app/user space) which FFX has been built as 32 Bits app.

so once you configured the game with high graphic settings. it uses higher memory and might be able to trigger the issue more eaiser.

we can use the tool called “editbin.exe” which is the small utility to allow us to change the flag of the process which is “/largeaddressaware” that can help to incrase the app/user space of memory up to 3/4GB based on OS. but at least it will be higer than 2GB as system default.

you can find “editbin” from Visual Studio.

and after I applied this flag. I can play the game for 4-5 hours for 2 days without any crash. hope this can help for some.

 

HAPPY GAMING…

Windows 10 – Universal Windows Platform ขอลองซักนิด

เนื่องจากว่า Microsoft โปรโมทนักหนากับ Universal Windows Platform (UWP) ที่เมื่อเขียนแล้วสามารถนำไปรันบน Windows 10, Windows Phone, Xbox, etc.. ซึ่งน่าจะเป็นการพลักดันครั้งสำคัญของ Microsoft ในการสร้าง Eco System ให้กลับมาแย่ง Market Share อีกครั้ง

โดยส่วนตัวแล้วผมก็มีประสบการณ์กับ C# + WPF มาพอสมควรทำให้ปรับตัวได้ไม่ยาก และ  UWP น้ันมี Architect เดียวกับ WPF ในการทำ User Interface.

เริ่มจาก

  1. Install Visual Studio 2015 Community Editoin ซึ่งใช้งานได้ Free 🙂
  2. สร้าง Project ใหม่เป็นแบบ UWP

newproj

3. ไฟล์ที่ถูกสร้างมาจาก UWP project ก็คุ้นหน้าคุ้นตา MainPage.xaml อีกแล้ว..

default_files

4. ลองมาดู Project Properties..ก็พบว่าเราสามารถ target App ของเราได้ตาม Windows 10 Build version

project_prop

5. มาดูฝั่ง XAML กันบ้าง ซึ่งตัว code ที่ Visual Studio สร้างมาให้ก็เป็นแค่หน้าจอขาวๆ

xaml_code.png

6. พวก Default Controls ของโลก WPF ก็ยังมาอย่างครบครัน

system_controls

7. ลองใส่ Button ดูก็ลอง ลาก แล้วก็วางได้เลย

xaml_code2

8. ลอง Double Click ที่ Button Object เพื่อเขียน Code Behide กัน
ลอง โชว์ Message Box

private async void button_Click(object sender, RoutedEventArgs e)
{
var dialog = new MessageDialog(“Hey Windows Universal Platform app!”);
await dialog.ShowAsync();
}

9. Compile App ได้เลยแล้วลอง Click ที่ปุ่ม Button

App เราก็จะถูก Style ด้วย Windows 10 – WUP UI เป็นค่าเริ่มต้น

msgbox_run

10. ถ้าอยากลองเทสกับหน้าจอหลายๆแบบ ใน Visual Studio ก็มีให้ปรับตามนี้

screen_res.png

11. ลองมาดู output files ของการ compile กันครับ ผลออกมาคือ .exe และ พวก dependencies assemblies ทั้งหลาย

app_output

12. ลอง double click เพื่อรัน App2.exe ตรงๆกันดูครับ

อ้าว error! แล้วเราจะรัน app ของเรายังไงล่ะครับ….

runtime_err.png

13. ลองไป เมนู Deploy App ดู

deploy.png

14. หลังจาก Deploy เสร็จ App ของเราก็มาโผล่ที่ Start Menu นั่นเอง

startmenu

และเนื่องจากผมลองเขียน app ที่มี scope ชัดเจนนิดนึง เลยลองเขียน App อ่านเวปสุดฮิต
แน่นอน Pantip นั่นเอง 🙂

ซึ่งตอนนี้ทาง app ก็ยังไม่มีอะไรมาก แค่ ListView ที่ทำ Data Binding กับ List Object เอามา render บนหน้าจอได้รวมถึงได้ลองใช้ HTTP req ในการดึง Data จาก Pantip.

pnatipw

ท้ายที่สุดจากการทดลองของผม UWP app นั้นเริ่มต้นได้ไม่ยากสำหรับคนที่มีความคุ้นเคยกับ C# และ WPF ซึ่งผมคิดว่าคนที่เคยเขียน Windows Form ก็น่าจะปรับตัวได้ไม่ยาก รวมถึง Visual Studio ที่เป็น IDE ที่ค่อนข้าง Powerful จึงทำให้การเขียนโปรแกรมทำได้เร็วขึ้น

 

ทดสอบ C# ด้วย .NET Core บน OSX

สำหรับคนที่เขียน C# บน Windows ก็คงต้องอยากที่จะให้มันเขียนได้บน Mac หรือ Linux ใช่มั้ยครับ จริงๆแล้วก็มี Mono Framework ที่ตอบโจทย์อยู่แล้ว แต่ถ้าเราต้องการ Native Experience ล่ะ?

.NET Core อาจจะเป็นคำตอบ (มั้ง)

เนื่องจากผมอยากลองดูว่า .NET Core ที่เป็น Open Source ของ .NET Framework ที่ทาง Microsoft ประกาศไว้ช่วงต้นๆปีที่แล้วจะเป็นยังไง ผมก็เลยลอง Setup ดูบน Mac เพื่อทดสอบ

เริ่มต้นจากทำตาม link นี้ http://dotnet.github.io/getting-started/ ซึ่งทางเวปจะ detect ให้ว่าตอนนี้เรากำลังใช้ OS อะไรอยู่

สำหรับ Mac – OSX จะต้องโหลดไฟล์ .pkg เพื่อทำการลง dotnet compiler ลงบนเครื่อง

หลังจากลงเสร็จก็มาเริ่มต้นจากใช้ Termial

Screen Shot 2559-01-10 at 11.48.19 PM

ลองสร้าง new default project ผ่าน commandline “dotnet new”

Screen Shot 2559-01-10 at 11.49.50 PM

ลอง “ls” ดูไฟล์ที่สร้างขึ้นมาจะได้แบบนี้ ซึ่งประกอบด้วย

  1. NuGet.Config
  2. Program.cs
  3. project.json

Screen Shot 2559-01-10 at 11.51.06 PM.png

ลองรัน command ตามที่ Getting Started บอกถัดไป “dotnet restore” เพื่อทำการ restore หรือ download พวก assemblies/dlls/modules ที่ได้กำหนดใน project.json มาเพื่อใช้ในการ Compile ตัวโปรเจคของเรา

Screen Shot 2559-01-10 at 11.54.08 PM

หลังจาก restore พวก dependencies ของโปรเจคเราแล้วลองสั่ง  compile และ run กันด้วย “dotnet run”

!!!! Error…

Unhandled Exception: System.IO.FileNotFoundException: Could not load file or assembly ‘System.Console, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a’ or one of its dependencies. The system cannot find the file specified.

Screen Shot 2559-01-10 at 11.56.20 PM

ปัญหานี้ก็คือมาดูที่ไฟล์ Program.cs

Code โปรแกรมเรามีการเรียกใช้ Console.WritLine หมายความว่ามันมี Dependency กับ System.Console ทำให้ Compile ไม่ผ่าน

using System;

namespace ConsoleApplication
{
 public class Program
 {
 public static void Main(string[] args)
 {
 Console.WriteLine("Hello World!");
 }
 }
}

ทีนี้มาดูไฟล์ project.json

{
 "version": "1.0.0-*",
 "compilationOptions": {
 "emitEntryPoint": true
 },
"dependencies": {
 "NETStandard.Library": "1.0.0-rc2-23616"
 },
"frameworks": {
 "dnxcore50": { }
 }
}

เราต้องทำการเพิ่ม dependencies เพื่อให้โปรเจคนี้รู้จัก dlls อื่นมากขึ้นเช่น System.Console ดังนั้นแก้ไฟล์ประมาณนี้

{
 "version": "1.0.0-*",
 "compilationOptions": {
 "emitEntryPoint": true
 },
"frameworks": {
 "dnxcore50": { 
"dependencies": { 
 "System.Console": "4.0.0-beta-*", 
 "System.IO": "4.0.11-beta-*", 
 "System.Runtime": "4.0.21-beta-*" 
 }
 }
 }
}

ลองรัน “dotnet restore” อีกรอบเพื่อโหลด dlls มาใหม่ก็จะยัง Error!!! ถ้าใช้ OSX 10.11.2+

ที่นี้ลองมาใช้ command นี้แทนในการ restore

“dotnet restore –runtime osx.10.10-x64”

จากนั้นก็ลอง “dotnet run” ในที่สุด Hello World! ก็ออกมาแล้ว

Screen Shot 2559-01-11 at 12.29.49 AM