본문 바로가기

Programing/Node.js

[node.js] C/C++ Addons 준비 node.js

Windows 7 x86 (32bit)에서 수행


1. node.js설치

 https://nodejs.org/ 에 방문하면 자신의 플랫폼에 맞는 다운로드 링크를 보여준다.


2. node-gyp 설치

 node.js를 설치하면 npm을 사용할 수 있는데 이 유틸리티를 이용한다.

 참고로, node-gyp는 node.js를 위한 네이티브 addon 모듈들을 컴파일하기 위한 node.js로 작성된 크로스-플랫폼 명령 라인 도구(node-gyp is a cross-platform command-line tool written in Node.js for compiling native addon modules for Node.js)이다.


 node-gyp 설치를 위해서는 명령 프롬프트에서 아래 명령을 수행한다.

C:\Users\namo\Desktop>npm install node-gyp -g

C:\Users\namo\AppData\Roaming\npm\node-gyp -> C:\Users\namo\AppData\Roaming\npm\node_modules\node-gyp\bin\node-gyp.js

node-gyp@3.0.3 C:\Users\namo\AppData\Roaming\npm\node_modules\node-gyp

├── graceful-fs@4.1.2

├── semver@5.0.3

├── osenv@0.1.3 (os-tmpdir@1.0.1, os-homedir@1.0.1)

├── fstream@1.0.8 (inherits@2.0.1)

├── nopt@3.0.4 (abbrev@1.0.7)

├── minimatch@1.0.0 (sigmund@1.0.1, lru-cache@2.7.0)

├── tar@1.0.3 (inherits@2.0.1, block-stream@0.0.8)

├── mkdirp@0.5.1 (minimist@0.0.8)

├── which@1.2.0 (is-absolute@0.1.7)

├── glob@4.5.3 (inherits@2.0.1, inflight@1.0.4, once@1.3.2, minimatch@2.0.10)

├── rimraf@2.4.3 (glob@5.0.15)

├── path-array@1.0.0 (array-index@0.1.1)

├── npmlog@1.2.1 (ansi@0.3.0, are-we-there-yet@1.0.4, gauge@1.2.2)

└── request@2.65.0 (aws-sign2@0.6.0, forever-agent@0.6.1, tunnel-agent@0.4.1, st

ringstream@0.0.4, oauth-sign@0.8.0, caseless@0.11.0, isstream@0.1.2, json-string

ify-safe@5.0.1, extend@3.0.0, tough-cookie@2.2.0, qs@5.2.0, node-uuid@1.4.3, com

bined-stream@1.0.5, form-data@1.0.0-rc3, mime-types@2.1.7, http-signature@0.11.0

, bl@1.0.0, hawk@3.1.0, har-validator@2.0.2)


3. node-gyp를 사용하기 위해 필요한 추가적인 의존성들

 - 파이썬: https://www.python.org/getit/windows 링크를 이용한다. v3.x.x 버전은 지원하지 않는다고 한다. v2.7.3을 권장하는데, 현재 최신버전인 2.7.10을 설치했다.

 - 컴파일러: 플랫폼에 맞는 개발도구를 사용한다. 요즘에는 무료 Visual Studio를 ms에서 제공하니 그것을 사용했다. > Visual Studio 커뮤니티

Visual Studio Community 2015가 설치되었다. 설치시에 용량을 줄이고자 프로그래밍 언어에는 'Visual C++'만 선택을 하였다.' 이렇게 하니 9.2GB의 용량이 필요했다.


4. Git

 개발환경이 제대로 되어 있는지 확인하기 위해 샘플 프로젝트를 받아 올 수 있다.

https://git-scm.com/ 


node.js는 알아서 PATH경로에 잡아 주기 때문에 설치 이후 명령 프롬프트를 실행시키면 되는데 Git이나 Python의 경우는 PATH경로에 추가해주어야 할 수 있다.



 변수 이름: PATH

 변수 값: %USERPROFILE%\AppData\Roaming\npm;C:\Python27;C:\Program Files\Git\bin;


PATH가 잘 걸리면 명령 프롬프트에서 버전을 확인해본다.


'XXX'은(는) 내부 또는 외부 명령, 실행할 수 있는 프로그램, 또는 배치 파일이 아닙니다.

라고 나오면 PATH가 제대로 걸리지 않은 것이다.



Node.js Addon 예제 빌드 해보기

Node.js Addon Examples 깃헙을 클론한다.

명령 프롬프트를 띄워서 작업 디렉터리로 이동(cd 명령 이용) 후에 git clone 명령으로 로컬 저장소로 클론을 하는 것이다.

여기서는 바탕화면에 복제하였다.


첫 번째 예제인 hello world를 빌드해보자.

clone한 디렉터리로 이동하고 안에 보면 버전이 두 가지가 있는데 0.12를 선택한다.

C:\Users\namo\Desktop>cd node-addon-examples


C:\Users\namo\Desktop\node-addon-examples>cd 1_hello_world


C:\Users\namo\Desktop\node-addon-examples\1_hello_world>cd node_0.12


C:\Users\namo\Desktop\node-addon-examples\1_hello_world\node_0.12>npm install

/

> hello_world@0.0.0 install C:\Users\namo\Desktop\node-addon-examples\1_hello_world\node_0.12

> node-gyp rebuild



C:\Users\namo\Desktop\node-addon-examples\1_hello_world\node_0.12>if not defined npm_config_node_gyp (node "C:\Program Files\nodejs\node_modules\npm\bin\node-gyp-bin\\..\..\node_modules\node-gyp\bin\node-gyp.js" rebuild )  else (node  rebui

ld )

이 솔루션의 프로젝트를 한 번에 하나씩 빌드합니다. 병렬 빌드를 사용하려면 "/m" 스위치를 추가하십시오.

  hello.cc

  win_delay_load_hook.c

     C:\Users\namo\Desktop\node-addon-examples\1_hello_world\node_0.12\build\Release\hello.lib


  hello.vcxproj -> C:\Users\namo\Desktop\node-addon-examples\1_hello_world\node_0.12\build\Release\\hello.node

bindings@1.2.1 node_modules\bindings


node.js 실행

C:\Users\namo\Desktop\node-addon-examples\1_hello_world\node_0.12>node ./

world


분석

addon을 사용하는 js 코드

// hello.js

var addon = require('bindings')('hello');


console.log(addon.hello()); // 'world'


C++ 코드

// hello.cc

#include <node.h>

#include <v8.h>


using namespace v8;


void Method(const v8::FunctionCallbackInfo<Value>& args) {

  Isolate* isolate = Isolate::GetCurrent();

  HandleScope scope(isolate);

  args.GetReturnValue().Set(String::NewFromUtf8(isolate, "world"));

}


void Init(Handle<Object> exports) {

  Isolate* isolate = Isolate::GetCurrent();

  exports->Set(String::NewFromUtf8(isolate, "hello"),

      FunctionTemplate::New(isolate, Method)->GetFunction());

}


NODE_MODULE(hello, Init)



Windows Native API 호출 추가해보기

위에서 사용했던 hello world에 함수를 추가해보았다.

사용하는 윈도우 네이티브 함수는 GetLocalTime 이다.

함수 자체에 대한 자세한 것은 MSDN에서 https://msdn.microsoft.com/ko-kr/library/windows/desktop/ms724338.aspx 를 참고한다.

#include <node.h>

#include <v8.h>

#include <Windows.h>


using namespace v8;


void Method(const v8::FunctionCallbackInfo<Value>& args) {

  Isolate* isolate = Isolate::GetCurrent();

  HandleScope scope(isolate);

  args.GetReturnValue().Set(String::NewFromUtf8(isolate, "world"));

}


void Now(const v8::FunctionCallbackInfo<Value>& args) {

  const int SizeBuf = 25;

  Isolate* isolate = Isolate::GetCurrent();

  HandleScope scope(isolate);

  SYSTEMTIME st;

  GetLocalTime(&st);

  char szTime[SizeBuf];

  sprintf_s(szTime, SizeBuf, "%d-%02d-%02d %02d:%02d:%02d.%03d",

   st.wYear, st.wMonth, st.wDay,

   st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);

  args.GetReturnValue().Set(String::NewFromUtf8(isolate, szTime));

}


void Init(Handle<Object> exports) {

  Isolate* isolate = Isolate::GetCurrent();

  exports->Set(String::NewFromUtf8(isolate, "hello"),

      FunctionTemplate::New(isolate, Method)->GetFunction());

  exports->Set(String::NewFromUtf8(isolate, "now"),

      FunctionTemplate::New(isolate, Now)->GetFunction());

}


NODE_MODULE(hello, Init)


REPL에서 수행해보았다.
C:\Users\namo\Desktop\node-addon-examples\1_hello_world\node_0.12>node
> var addon = require('bindings')('hello');
undefined
> addon
{ hello: [Function],
  now: [Function],
  path: 'C:\\Users\\namo\\Desktop\\node-addon-examples\\1_hello_world\\node_0.12
\\build\\Release\\hello.node' }
> addon.now();
'2015-10-18 16:05:12.872'
> addon.now();
'2015-10-18 16:05:16.585'
>


기존 나모의 노트를 아카이브 해놓은 것이 있어서 링크를 달아놓았다. 저 글을 처음 작성했을 때랑 node.js버전이 많이 바뀌어서 add-on 작성 코드가 바뀌었다.

 http://jacking.tistory.com/1017

'Programing > Node.js' 카테고리의 다른 글

node.js 뼈대(skeleton) - 템플릿(template)  (0) 2018.03.14
python 뼈대(skeleton)  (0) 2018.03.14
libuv - uv_pipe_open 에러 : EINVAL  (1) 2014.04.15
libuv 계층도  (0) 2014.04.15
libuv가 많이 바뀌었다.  (0) 2014.04.10