티스토리 뷰
Node.js의 명성과 장점은 굳이 제가 언급할 필요도 없을 것입니다.
획기적인 생산성을 제공하기로 유명한데,
그래도 저같은 C 개발자가 처음 Node.js 프로젝트에 합류했을 때에는
여전히 일부 모듈만이라도 C로 개발하고 싶은 욕구가 마음 속 깊은 곳에서 부터 꿈틀꿈틀댑니다.
또는 내가 만든 C/C++ 라이브러리를 Javascript Language에도 binding해서 제공하고 싶다면 비슷한 욕구가 생길 것입니다.
Node.js에서 require로 load해 쓸 수 있는 이런 C/C++로 제작된 Shared Object를 Addon이라 부릅니다.
Addon을 처음 개발할 때, 간단히 따라할 수 있는 예제 코드와 node-gyp 라는 빌딩 툴이
Node.js 홈페이지에 매우 쉽게 정리되어 있습니다.
C++ Addons : https://nodejs.org/api/addons.html
node-gyp : https://github.com/nodejs/node-gyp
그러나, 저는 vi와 Makefile을 좋아하는 고전(?) 개발자이기 때문에 node-gyp 사용이 달갑지 않습니다.
다른 Library linking은 어떻게 하지?
기존 컴파일 방법을 유지하고 싶은데...
등과 같은 고민이 시작됩니다.
다른 Opensource들의 선행 사례를 참조하다 보니,
그냥 Makefile로 컴파일 하고도 Node.js에서 읽을 수 있는 Addon을 생성하는 것을 발견했습니다.
시행착오를 거쳐 알아낸 내용을 결론부터 말씀드리자면,
약속된 Function Symbol이 존재하는 Shared Library 파일이면 모두 Node.js의 Addon이 될 수 있습니다.
이는 흔히 우리가 Library를 dlopen 후 약속된 Symbol을 찾아 약속된 형식으로 Call하는 로직을
Node.js에서도 그대로 사용한 듯 싶습니다.
그러면 한번 위 Node.js 사이트에 소개된 예제코드를 약간 변형하면서 gcc로 빌드하는 방법을 보여드리겠습니다.
1. Node.js 설치
저는 Node.js v5.12.0 을 이용했습니다.
일반적으로 Ubuntu에서 apt-get으로 nodejs 및 nodejs-dev를 설치할 경우,
LTS 버젼인 4.x 가 설치되는데 버젼 별로 헤더파일의 위치가 달라집니다.
본 예제를 따라하시려면 5.x를 설치하시기 바랍니다.
설치 방법 : https://github.com/nodesource/distributions#deb 에서
Node.js v5.x 항목 중 본인 OS에 맞는 설치 방법 실행
2. 코드 작성
#include <node/node.h> // 중요 1. header #include <iostream> namespace demo { using v8::FunctionCallbackInfo; using v8::Isolate; using v8::Local; using v8::Object; using v8::String; using v8::Number; using v8::Value; void Method1(const FunctionCallbackInfo<Value>& args) { Isolate* isolate = args.GetIsolate(); args.GetReturnValue().Set(String::NewFromUtf8(isolate, "world")); } void Method2(const FunctionCallbackInfo<Value>& args) { if (args.Length() != 2) { std::cout<<"Invalid Parameters"<<std::endl; return; } if (args[0]->IsNumber() && args[1]->IsNumber()) { double value = args[0]->NumberValue() + args[1]->NumberValue(); Isolate* isolate = args.GetIsolate(); Local<Number> num = Number::New(isolate, value); args.GetReturnValue().Set(num); } } void init(Local<Object> exports) { // 중요 3. Method 정의 NODE_SET_METHOD(exports, "hello", Method1); NODE_SET_METHOD(exports, "sum", Method2); } NODE_MODULE(addon, init) // 중요 2. 모듈 정의 }
코드에서 중요한 부분은
1) 첫 라인의 header 참조입니다. Node.js 5.x 의 경우 node/node.h를 참조하고 있습니다.
(물론 컴파일 인자에 따라 폴더명은 생략할 수도 있겠지요)
2) 가장 하단부 입니다. NODE_MODULE 이라는 매크로를 반드시 사용해야 하고,
첫 란에 모듈 이름을, 두번째 란에 초기화 함수를 지정합니다.
3) 위의 초기화 함수 안에서 NODE_SET_METHOD 매크로를 이용해, 위와 같이 원하는 만큼 method를 지정해 줍니다.
첫 인자는 init()의 파라미터, 두번째 인자는 Node.js에서 호출할 때 쓸 Method명,
세번째 인자는 실제 C++ 코드에서 호출되는 Method명 입니다.
Method1은 그냥 "world"라는 String을 리턴하는 내용이고,
Method2는 두 파라미터 Number의 합을 리턴하는 내용입니다.
3. 컴파일 하기
g++ -std=c++11 --shared -fPIC -o test.node module.cc
컴파일은 매우 단순합니다.
module.cc 라는 코드를 test.node 라는 이름의 shared library 로 컴파일 하였습니다.
4. 실행 해보기
$ node
> test = require('./test.node')
{ hello: [Function: hello], sum: [Function: sum] }
[ require() 로 모듈 로드 시 Method들 정보를 볼 수 있습니다. ]
> var str = test.hello()
undefined
> console.log('Str : ' + str)
Str : world
undefined
[ hello() method의 return 값을 str에 담은 뒤 console에 print해서 확인해 보았습니다. 'world'라는 string이 정상적으로 획득되었습니다. ]
> test.sum(1)
Invalid Parameters
undefined
[ sum() method에 parameter 갯수를 한개만 주었을 때. ]
> test.sum(1, 2,2)
Invalid Parameters
undefined
[ sum() method에 parameter 갯수를 세개 주었을 때. ]
> test.sum(1, 2.2)
3.2
[ sum() method에 parameter 갯수를 두개(정상) 주었을 떄. 더한 값 3이 화면에 출력 됨. ]
그 외, 파라미터 핸들링 등에 관한 내용은 V8의 Class들을 공부해야 합니다.
'Linux 개발' 카테고리의 다른 글
casync 알아보기 #2 (빌드 & 테스트) (1) | 2017.06.29 |
---|---|
casync 알아보기 (Content Addressable Data Synchronizer) (0) | 2017.06.28 |
표준출력 stderr, stdout 을 파일 등으로 redirection 하기 (0) | 2016.09.18 |
명령어 자동완성을 위한 Bash script 작성 (우분투) (0) | 2016.04.23 |
CMake를 이용한 패키지 빌드 (0) | 2016.04.13 |
- Total
- Today
- Yesterday
- node.js
- Container
- casync
- Lennart Poettering
- Tizen SDK
- 푸시
- Gear S3
- IOT
- 타이젠
- Tizen Studio
- Samsung Push
- libfuse
- Wearable
- Gear s2
- content-addressable storage
- Push Service
- nodejs
- Tizen
- node-gyp
- Tizen Push
- Tizen Emulator
- GCM
- NPPi
- Push
- systemd/casync
- Samsung gear
- samsung
- gear
- CUDA
- content addressable storage
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |