C++ 모듈을 만드는 법은 알았는데 디버깅 하는 법을 알 수가 없었다.

내가 사용하고 있는 툴은 Visual Studio Code이다.
이 툴을 쓰게된 이유는 미국에 사는 친구가 요즘 Node.js가 미국에서 대세고 사용하는 툴은 주로 위에 것을 쓴다고 해서, 나도 그냥 썻다.
아톰이란 것도 있길래 살짝 고민했는데, 써보니 확실히 가볍고 좋은 것 같다.

저 툴을 사용하면  - Node.js설치하고 path설정후, 재부팅해주면 - 자동으로 .js 파일들은 디버깅이 가능하다.

근데 C++로 만든 .node 모듈 파일들은 디버깅을 할 수가 없었다.
솔직히 그냥 printf가 콘솔로 출력 되면 그걸로 디버깅 하려 했지만... 되지 않았다.
그래서 디버깅을 하기 위한 여행을 떠났다.

최초로 참고한 자료는 아래의 싸이트 이다.
https://computer-vision-talks.com/how-to-debug-nodejs-addons-in-visual-studio/

How to debug node.js addons in Visual Studio

While working on CloudCV I encountered problems in node.js addon written in native code. For CloudCV I use node.js with C++ Addon to separate high-performance algorithms (C++) from high-level networking API which node provides. In this tutorial I’m going to reveal best practices on debugging C

computer-vision-talks.com


동영상도 있고, 어떻게 디버깅을 할수 있는지 자세히 적혀 있다.
반나절 넘게 끙끙거리면서 결국 성공했다.
하지만 문제점들이 있다.

1. 내가 사용 하는 Visual Studio Code가 아닌 Visual Studio 2013을 기반으로 설명하고 있다. 그래서 개발 환경을 바꿔야 했다.
     - 사실 이건 그렇게 큰 문제는 아니였다.

2. 기존에는 커맨드 창에서 node-gyp를 이용해서 컴파일을 했는데, 이 컴파일 과정에서 비쥬얼 스튜디오 2013을 동작시키고 있으면, 파일 엑세스 에러가 걸려서 컴파일이 안된다. 
     - 어떤 파일인지는 정확히 기억이 안나지만, 파일 하나를 비쥬얼 스튜디오 2013이 점유 하고 있는데 이놈때문에 컴파일 중에 에러가 난다. 그래서 매번 컴파일할 때 마다, 비쥬얼 스튜디오를 끄고 켜고를 반복해야 했다. 이러면 개발이 불가능은 아니지만, 열받아서 능률이 떠러진다.

3. 이 문제가 가장큰 문제인데, node-gyp를 통해 컴파일을 하고 나면 프로젝트 설정이 초기화 됐다. 굉장히 중요한 문제이니 잘읽어 보자.

- 우선 node-gyp가 사용 하는 컴파일러는 비쥬얼 스튜디오에서 사용하는 컴파일러와 동일하다.
- 어디에 확실히 그렇다고 쓰여있는 것을 보지는 않았는데.. node-gyp환경 구성을 보면 파이썬과, 비쥬얼 스튜디오 컴파일 환경이 필요 한데. 그곳에서 유추 할 수 있다. 
- 또한 디버깅용으로 컴파일하고 나면 binding.sln 파일이 생기는데, 이것은 비쥬얼 스튜디오 프로젝트를 생성하면 나오는 파일과 동일 하다. 
- 위에 참고한 사이트를 보면, binding.sln 파일을 비쥬얼 스튜디오 2013을 통해 열어서, 이런 저런 설정(좀있다 자세히 이야기 하겠다.)을 하는데 그 설정을 해야만 디버깅이 가능하다.
-근데 문제는 다시 node-gyp를 통해 컴파일을 하고 나면, 해놨던 설정들이 전부 원래대로 돌아간다.
-즉 매 컴파일 마다 설정을 다시해줘야 한다.

결론은 위 방법을 이용하면, 디버깅은 가능하다. 하지만 개발용 디버깅을 사실상 불가능 하다.


그래서 나는 Visual Studio Code를 통해서 컴파일도 하고, 디버깅을 할 수 있도록 도전해 봤다. 사실 printf만 콘솔창에 나왔어도 나는 안했을 것이다. 내가 만들려는 모듈은 아주 작은 모듈인데.. 배보다 배꼽이 큰 상황이다.

위 과정을 통해 알게된 사실들을 나열한다.

1. node-gyp에서 사용하는 컴파일러는 비쥬얼 스튜디오 환경에서 사용하는 C++ 컴파일러와 동일하다.

2. .node파일(node.js addon 파일)은 동적 라이브러리 파일 .dll과 동일하다. 때문에 C++ 디버거로 디버깅이 가능하다.

3.디버깅을 할때 사용하는 디버거는 (로컬 Windows 디버거)이다.

4. 디버깅을 실행 할때, '디버거를 설정 하는 부분'과, '디버깅을 하기위해 프로그램 실행을 어떻게 해야하는지' 두가지를 설정 해야 한다.

5. 디버깅을 하기위해 프로그램 실행하는 방법은 아래 그림과 같이.
   - 명령어  : 프로그램을 실행시킬 프로그램 (C:\경로\node.exe)
   - 명령인수(인자)  :  처음으로 시작하는 js 파일 (app.js)
   - 작업 디렉터리 :  sln파일이 있는 곳에서 한 경로 위쪽 (..)
등등을 설정 해야 하는구나.

디버깅을 하기위해 프로그램 실행을 어떻게 해야하는지 설정


위에 나열한 내용을 토대로 문제를 풀어 갔다.

자 같이 문제를 풀어 보자.

우선 아까 이야기한 사이트
https://computer-vision-talks.com/how-to-debug-nodejs-addons-in-visual-studio/
의 내용을 토대로 진행했으니, 이곳에서 하라는 순서를 기반으로 이야기하겠다.

시작전

1. node-gyp를 설치하세요
    npm install -g node-gyp

- 위에 명령어 하나로 해결되면 좋은데.. 나는 그리 안됐다.
https://oj-tube.tistory.com/entry/Nodejs-C-%EB%AA%A8%EB%93%88-%EC%A0%9C%EC%9E%91-%ED%95%98%EA%B8%B0 를 참고하면 해결 가능하다.

Node.js C++ 모듈 제작 하기

C++ 언어로 모듈을 제작해서 간단한 출력을 하는 것 까지의 내용이다. 그 이후에 진행 되는 내용들이 있지...

blog.naver.com



2. nan을 설치하세요
npm install -g nan

nan은 모듈 개발 API인데 내가 진행할 예제는 필요없다.
하지만 위에 사이트에서 사용한 예제는 nan을 사용했다.
이놈을 이용하면 좀 더 간편하게 모듈을 제작할수 있고, 이러 저러한 단점을 보안해놨다. 하지만 결론적으로 v8에 의존적이라 v8 버전이 바뀌면 다시 컴파일 해야한다는 문제는 해결하지 못했고, 그 것을 해결하기 위해 n-api라는 프로젝트가 현재 진행 중이다. 하지만 n-api를 사용해서 컴파일하면, 하직 시험적 단계라는 경고문이 뜬다. 아무튼 지금 신경쓸 단계는 아니다. 우리는 디버깅이 목적이다.


3. node.js 소스를 받아 debug 모드로 빌드 하세요.

이 과정이 필요한 이유는 디버깅하면서 내가 만든 모듈 외에 node.js 관련 소스 부분도 디버깅이 가능하기 때문이다. 근데 내가 해보니 꼭 이거 안해도, 내가 만든 모듈은 그냥 릴리즈용 node.exe에서도 가능했다.

소스를 받았던 사이트는.. 
https://nodejs.org/ko/download/

다운로드 | Node.js

최신 LTS 버전: 8.11.1 (includes npm 5.6.0) 플랫폼에 맞게 미리 빌드된 Node.js 인스톨러나 소스코드를 다운받아서 바로 개발을 시작하세요. LTS 대다수 사용자에게 추천 현재 버전 최신 기능 Windows Installer node-v8.11.1-x86.msi macOS Installer node-v8.11.1.pkg Source Code node-v8.11.1.tar.gz Windows Installer (.msi) 32-bit 64-bit Windows Binary (.zip) 32-bit 64-bi

nodejs.org

이고, 버전은 8.11을 받았다.
참고로 컴파일은 겁나게 쉽다.
진짜 내 컴파일 역사상 가장 쉬웠다.
windows에서 진행했는데.
그냥 tar.gz파일 받아서, 압축 풀고, vcbuild.bat 파일만 더블 클릭하면 컴파일이 된다.
단, 그냥 더블 클릭하면 릴리즈 모드로 컴파일 되니, 디버그 모드로 컴파일하고 싶으면 커맨드 창 하나 실행하고, 해당 디렉토리로가서 'vcbuild.bat debug' 라고 실행 하면 된다.
근데, 참고 사이트에서는 옵션 두개를 더 붙여서..
'vcbuild.bat debug nosign x64 ' 라고 실행 하라고한다.
옵션이 무엇을 의미하는지 읽어 봤는데. 잘 기억이 안난다. x64는 64bit용이고 nosign이 무엇이엇는지 기억이 잘 안난다.
그래서 다시 한번 읽어 봤다 -_-;
서명을 안한다는 건데.. 기본이 vcbuild는 nosign이라고 한다.
결론은 옵션 2개가 전부 그냥 디폴드 값이니깐, 안써도 무방하다.

'vcbuild.bat debug' 만 하면된다.

그렇게 실행하고 나면 10~30분정도 후에 '설치경로\Debug\node.exe' 파일이 생긴다.

실험 삼아 이놈을 실행하고, console.log("hello~~"); 해보니 잘된다.
릴리즈 node.exe가 아닌 디버깅 정보가 담긴 node.exe가 만들어 진것이다. 이제 이놈을 사용해서 디버깅을 해보자.
위에도 말했지만 릴리즈 node.exe를 사용해서 모듈 디버깅 잘된다.


- 자 이제 부터는 응용 파트이다. 위에서 얻어낸 모든 정보를 동원해 원하는것을 얻어 보자.

4. Visual Studio Code와 C/C++ extension 을 설치하자.

우선 Visual Studio code는 설치됐다고 믿는다.
https://code.visualstudio.com/  여기서 다운 받자.

Visual Studio Code - Code Editing. Redefined

Visual Studio Code is a code editor redefined and optimized for building and debugging modern web and cloud applications.  Visual Studio Code is free and available on your favorite platform - Linux, macOS, and Windows.

code.visualstudio.com


그리고 C/C++ extension을 설치하자.
https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools 이놈을 설치해야 하는데.
Visual Studio Code를 실행후 ctrl + shift + x 누르고, 검색에 C++ 하면
가장 위에 뜨는 놈이 우리가 설치해야할 C/C++ extension이다.
MS에서 제공하는 것이고 생긴 모양은 아래와 같다.

C/C++ Extension 생긴 모양


5. 우리가 컴파일할 코드를 구성하자.
전에 쓴 글 https://blog.naver.com/ojwojwoj/221266536930에 있는 예제에 변수 a선언 하고, printf로 찍어 보는 것만 추가 했다.

파일1 - app.js
const hangle = require('./build/Debug/hangleModule.node');
console.log(hangle.hello());

파일2 - hangleModule.cc

#include <node.h>

namespace demo {

using v8::FunctionCallbackInfo;
using v8::Isolate;
using v8::Local;
using v8::Object;
using v8::String;
using v8::Value;

void Method(const FunctionCallbackInfo<Value>& args) {
Isolate* isolate = args.GetIsolate();
char test[] = "test etasdklfnaskldfnklasdnfklansdfklnasklfnasklndflasdkf";
args.GetReturnValue().Set(String::NewFromUtf8(isolate,test ));
int a;
a=2;
printf("hello ??? %d\n",a);


}

void init(Local<Object> exports) {
NODE_SET_METHOD(exports, "hello", Method);
}

NODE_MODULE(NODE_GYP_MODULE_NAME, init)

}

파일3 - binding.gyp

{
"targets": [
{
"target_name": "hangleModule",
"sources": [
"hangleModule.cc"
],
"include_dirs": ["<!(node -e \"require('nan')\")"#nan api사용시 추가. 지금은 사용안함
}
]
}





6. launch.json 파일을 구성하자.

이 파일은  위에서 언급한 '디버깅을 하기위해 프로그램 실행을 어떻게 해야하는지'를 설정하는 부분과 비슷하다.

디버깅을 하기위해 프로그램 실행을 어떻게 해야하는지 설정


이 정보를 통해 디버깅이 시작된다. 
어떤 디버거를 사용할지 등등을 설정하는 것이다.
이파일은 작업디렉토리에 .vscode 디렉토리 밑에 있어야한다.
이 파일과 .vscode디렉토리는 cc파일에서 f5를 눌러 디버깅을 할려고 하면, 자동으로 생성되고, 반드시 작성해야한다고 알려준다.

개 노가다 끝에 완성된 launch.json 파일은 이와 같다.

{
"version": "0.2.0",  //버전은 본인이 알아서 설정.
"configurations": [
{
"name": "C++ Launch (Windows)",  //그냥 이름이다. 
"type": "cppvsdbg",  //이거 정말 중요하다. 정말 정말
"request": "launch", //-_-; 실행하라는 거지뭐
"program": "C:\\ProjectWork\\NodeJsD\\Debug\\node.exe",  //디버깅할 대상을 실행 시킬 프로그램
// "program": "C:\\ProjectWork\\NodeJs\\node.exe",  //릴리즈 버전 node.exe
"args": [
"${workspaceRoot}\\app.js"    //node.exe app.js 이렇게 실행 시키기 위함.
],
"symbolSearchPath": "D:\\프로젝트\\18-스마트미러\\hangle\\build\\Debug",   //디버깅 정보가 담긴 파일(pdb) 위치 
"externalConsole": false,  //외부 콘솔을 사용할것인지?
"logging": { //로그 정보
"moduleLoad": true,
"trace": true
},
"cwd": "${workspaceRoot}"   //작업 드랙토리
}
]
}



위에 주석으로 대충 설명해놨는데 중요한것을 집고 넘어 가겠다.
program : 디버깅 시작시 어떤 프로그램으로 디버깅할 프로그램을 실행 시킬지 적는 부분이다. node.exe를 통해서 시작하면 된다. 우리가 위에서 진행한 디버그 버전 node.exe를 통해서 하면된다. 릴리즈용도 된다.

args : node.exe에 넘겨줄 인자다. app.js를 넘겨주면 되는데. 앞에 ${workspaceRoot} 라고 적은 이유는 처음에 내가 잘몰라서 cwd를 설정 안하고 컴파일을 했었는데.. app.js를 찾지 못하는 에러가 발생해서, 임시 방책으로 적어논것이다. 하지만 이제는 밑에 cwd를 설정 했기 떄문에 그냥 지우고 app.js만 써도 된다. ${workspaceRoot}는 현재 작업 디렉토리를 의미한다.

symbolSearchPath : 위에 적어 논대로 디버깅 정보가 담긴 파일(pdb)위치를 적으면 된다.

externalConsol : 디폴트 값이 true인데, 그렇게 되면 외부 콘솔창이 뜨고 거기서 node.exe가 실행된다. 그럼 종료 되면 획 사라지고, 또 환경 변수도 꼬이고 이런 저런 문제가 있길래 그냥 false로 했다, 그럼 visual studio code 디버그 콘솔창에서 콘솔 정보들을 볼수 있다. 그리고 printf 결과도 볼 수 있다.

cwd : 위에 언급한 그대로이다. 현재 작업 디렉토리 설정이다.

type: 우선 결론은 cppvsdbg라고 입력해야 하고, 이렇게 입력해야 디버거를 visual studio 2013에서 사용했던 디버거와 동일한 것을 사용한다.

저것을 몰라서 고생했는데. 그 이유는 다음과 같다.



1. 그냥 f5를 눌려서 생성되는 aunch.json 파일 기본들은 아래와 같다.
- 몇몇 세부 내용은 내가 채워 넣은것인데..
- type을 보면 기본으로 cppdbg로 설정되어있다.

{
// IntelliSense를 사용하여 가능한 특성에 대해 알아보세요.
// 기존 특성에 대한 설명을 보려면 가리킵니다.
// 자세한 내용을 보려면 https://go.microsoft.com/fwlink/?linkid=830387을(를) 방문하세요.
"version": "0.2.0",
"configurations": [
{
"name": "(gdb) Launch",
"type": "cppdbg",
"request": "launch",
"program": "C:\\ProjectWork\\NodeJsD\\Debug\\node.exe",
"args": [
"app.js"
],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [],
"externalConsole": true,
"MIMode": "gdb",
"miDebuggerPath": "/path/to/gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
]
}
]
}



type은 두가지가 가능한데.. 
cppdbg와 cppvsdbg이다.
cppvsdbg는 자동으로 비쥬얼 스튜디오 디버거를 찾아서 디버깅을 해주고,cppdbg 는 miDebuggerPath 설정을 통해 따로 디버거를 설정해줘야 한다.
내가 참고한 자료들은 전부 cppdbg  type을 사용했고, 디버거로는 mingw64를 설치해서 gdb를 이용했다.
나도 그렇게 진행했는데. 디버깅 실행까지는 됐는데..
디버깅 정보를 볼수는 없었다.

사실 당연한 것이었다.
- 디버깅 정보를 남긴 컴파일러는 비쥬얼 스튜디오에서 만든 것이고,
- 디버깅 정보를 통해 디버깅을 할려는 놈은 엉뚱한 gdb이니..
- 디버깅 정보가 gdb에서 사용하는 포맷과 다르니 ..
볼 수 없는 것이 당연한 것이다.

이 사실은 전에 같은 arm칩을 쓰더라도, armcc랑 gnu에서 만든 arm용 gcc랑 생성된 내용이 다르다는 것을 보고 알고 있었다.

만약에 .node를 만들때, gcc를 이용해서 만들었다면 gdb로 디버깅이 가능했을 것이다.
하지만 비쥬얼 스튜디오에서 제공하는 컴파일러를 이용했으니, 비쥬얼 스튜디오에서 제공하는 디버거를 이용해야만 했다.

난 그방법을 miDebuggerPath 에 로컬 윈도우 디버거 실행 파일을 지정하는 방식으로 해결하려 했다. 하지만 아무리 찾아도 윈도우 디버거 실행 파일을 찾지 못했고 포기하려고 했는데.

https://code.visualstudio.com/docs/languages/cpp 싸이트를 꼼꼼히 읽다보니 해결방법을 찾은 것이다.
type 부분이 미묘하게 달랐던 것..

아무튼 이래저래 그디어 디버깅에 성공 했다.

하지만, 컴파일을 매번 수동으로 하기 싫었는데. 

ctrl + shift + b 를 누르면 자동으로 컴파일 되는 방법이 있었다.


7. tasks.json 파일을 구성하자.

컴파일시 참조 하는 json 파일이고 이놈도 .vscode 디렉토리 밑에 있어야 한다.

이런 저런 방법이 있을텐데..
나는 아래와 같이 작성 해서 성공 했다.


{
"version": "2.0.0",
"tasks": [
{
"label": "build hello world",
"type": "shell",
"windows": {
"command": "./build.bat"
},
"group": {
"kind": "build",
"isDefault": true
}
}
]
}



원래는 windows 안에 command가 아니고
그냥 밖에 command가 있고,
args에 인자를 넣는 형태인데.
그냥 build.bat 파일을 하나 만들고 필요한 내용을 다 때려 박고,
그 파일을 실행하는 형태로 바꿨다.

원래는 이런 형태다. (형태만 참조 할것)

{
"version": "2.0.0",
"tasks": [
{
"label": "build hello world",
"type": "shell",
"command": "g++",  //컴파일러
"args": [ // 넘길 인자들
"-g",  
"helloworld.cpp"
]
}
]
}


아무튼 build.bat 파일엔 다음과 같이 썼다.

set npm_config_node_gyp=C:\ProjectWork\NodeJs\node_modules\npm\node_modules\node-gyp\bin\node-gyp.js

set PYTHON=C:\Users\user\.windows-build-tools\python27\python.exe

node-gyp configure build --nodedir="C:\ProjectWork\NodeJsD" --debug


npm_config_node_gyp과 PYTHON 변수 설정은 실행 하는 커맨드 창이 비쥬얼 스튜디오 code여서 적용이 안되있길래, 다시 해준것이고 (안하면 컴파일 안됨)

node-gyp configure build --nodedir="C:\ProjectWork\NodeJsD" --debug 

가 컴파일 하는 명령어이다.

아마도, pm_config_node_gyp과 PYTHON 변수 설정은 환경 변수 설정에서 해주면 전체 적용 되기 때문에 따로 안해도 될것 같고..

node-gyp configure build --nodedir="C:\ProjectWork\NodeJsD" --debug  는

위에
"command": "g++",  //컴파일러
"args": [ // 넘길 인자들
"-g",  

를 잘 이용하면 별도의 bat 파일은 안 만들어도 될것 같다.
우선 나는 이것도 충분히 괜찮아서 더이상 진행은 안했는데.
bat 파일 만들기 싫으신 분은 끙끙해 보고 성공 여부를 알려주면 좋겠다.

node-gyp configure build --nodedir="C:\ProjectWork\NodeJsD" --debug에 대해서 조금 설명하자면

--debug를 붙여야 디버깅 정보를 남긴 node 파일이 만들어지고,
--nodedir를 설정해주면 node.exe에 관련된 정보를 디버깅 할때, 소스 까지 디버깅이 가능해진다.

처음 언급한 사이트에서는 
What is really important here, is --nodedir="c:\Develop\node-v0.12.0" flag, which indicates to link against node in specified folder rather than system wide available.
라고 말한다.

아무튼 위 bat 파일을 만들고, 바로 실행 할수 있게 작업 디렉토리에 넣어 둔다.

그리고 ctrl + shift + b 를 누르면 bat파일이 실행 되면서 컴파일이 된다.

 

Visual Studio Code에서 gyp-node 컴파일 하는 장면



8. 디버깅을 해보자.

 f5를 누르면 디버깅이 가능하다.

디버깅 장면

브레이크 포인트도 잘 동작하고, 변수 내용도 잘 보인고.. 호출 스택도 보인다.

이제 원하는 모든 것을 이뤄냈다!
이제 개발만 하면된다.

- 한계점
js 파일들은.. 디버깅이 안된다. ㅠ.ㅠ
js파일일땐 node.js용 디버거가! cc파일일때 비쥬얼 스튜디어 디버거가! 동작하면 좋겠는데.. 그건 안된다.
따로 따로 디버깅을 해야한다는 단점이 있다.


- 맺으며
내가 잘 못찾아서 그런지.. 어디에도 visual studio code를 이용한 node.js  C++ 모듈 디버깅하는 법이 없어서, 글을 작성했다.

사실 누가 보겠냐만은.. 내가 본다.
기록하지 않은 내용은 몇달있으면 암것도 기억이 안난다.


옜날에 면접 볼때 면접관이 한말이 기억난다.

면접관 : 이건 어떻게 만드셨나요? 

나 : 대충 이렇게 이렇게 만들었는데.. 정확히 기억이 안나네요. 제 프로젝트 노트에 적어 놨는데...

면접관 : 그럼 이건요?

나 : 이렇게 저렁게 이렇게요.. 근데 디테일한건 기억이 기억이 잘.. 제가 만든건 맞는데.. 그것도 적어 놧어요..

면접관 : 아니 전부 까먹나요?

나 : ...그러게요 근데 제가 만든거 맞아요. 그때 엄청 고민해서 만들었어요. 지금 3년째 문제 없이 잘 돌아가고 있어요.

면접관 : ㅡㅡ+ (눈초리)

좀 억울했다. 누가 그걸 다 기억한단 말인가 ㅠ.ㅠ
그런데 있나 보다 ㅠ.ㅠ
나는 못하니 적자.

 

'개발 > Node.JS' 카테고리의 다른 글

비슷한 문자 찾아내는 Node.js C++ 모듈  (0) 2020.02.07
Node.js C++ 모듈 제작 하기  (0) 2020.02.07

C++ 언어로 모듈을 제작해서 간단한 출력을 하는 것 까지의 내용이다.

그 이후에 진행 되는 내용들이 있지만, 딱 위의 내용까지만 서술한다.

우선, Node.js는 알다시피 자바스크립트 언어를 사용한다.

편하지만 느리다는 단점이 있는데, C++ 모듈을 만들어서 그 모듈을 가져다 사용 하면 속도가 상당히 빨라진다.

그래서 사용한다고 한다.

내가 사용한 이유는 String을 bit연산도 하고..

byte 단위로 뿌셔서 검색하는 기능을 만들어야 하는데..

자바스크립트로는 자유롭게 그런 기능을 할 줄도 모르고..

할수도 없는 것 같아서, 이런 방법을 사용했다.

우선 C++를 모듈을 제작한다는 것은,

windows의 dll과 비슷하고,

linux에서는 so와 비슷하다고 생각하면 된다.

이미 이 글을 읽는 사람은 어느 정도 아는 사람이 분명하니, 자세한것은 생략 하겠다.

jni도 그렇듯이.. 네이티브 코드랑 어떤 다른 언어를 연결할 때는 항상 크로스 컴파일러가 필요하고 특정 규칙대로 코드를 짜야하는데..

이럴때 사용 하는 도구가 node-gyp이다.

저 node-gyp를 이용해서, .node확장자를 가진 모듈을 만들고 나면,

그 모듈을 node-js에서 불러다 써야 하는데..

불러다 쓰는 기능을 해주는 모듈이

node-bindings이다.

자 설치하자.

1. 우선 node-gyp를 설치하자

windows cmd 창으로 가자. 참고로 앞으로 하는 작업은 전부 관리자 권한으로 실행된 cmd 창에서 진행 하자. 관리자 권한을 요구하는 경우가 있다.

npm install node-gyp -g

이러면 글로벌로 설치되서 어디서든 node-gyp 명령을 내릴 수 있다.

2. 그다음은 node-bindings를 설치하자.

근데 이놈은 글로벌로 설치하지말고, 특정 프로젝트 폴더에서만 사용하도록 설치한다.

프로젝트 폴더로 이동하자.

npm install bindings --save

위 명령을 내리자..

내가 참고한 글에서는 node-bindings를 설치하라고 되어 있었는데..

안되서 해당 싸이트로 가서 글을 읽어보니 bindings로 바뀐 것 같다.

아무튼 설치 한후에.

이제 코딩을 하자.

3. binding.gyp 파일 만들기

node-gyp는 빌드 전에 configure를 한번 해야 하는데.

configure때 사용하는 파일이 binding.gyp이다.

위파일을 프로젝트 폴더에 만들고,

아래 내용을 적어 보자!

{

"targets": [

{

"target_name": "hangleModule",

"sources": [ "hangleModule.cc" ],

}

]

}

내가 만들 파일은 hangleModule.cc이다.

타겟 네임에 따라 .node 파일이 만들어 진다.

나같은 오류를 겪지는 안겠지만..

나는 위의 기본 폼을 ctrl + c , ctrl +v 했는데.

" 기호가 ”라는 기호로 복사가 되서 문법 에러가 났다..

둘이 가만히 보면 차이점을 찾아 내기가 쉽지 않다..

그나마 전에 이런 경험이 있어서 금방 찾기는 했다.

4. 모듈 파일 코딩하기.

우선 지금의 목적은 hello world를 출력해서 화면에 보는것이다.

그러니 코드를 너무 이해하려고 하지는 말자.

#include <node.h>

namespace demo {

using v8::FunctionCallbackInfo;

using v8::Isolate;

using v8::Local;

using v8::Object;

using v8::String;

using v8::Value;

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

Isolate* isolate = args.GetIsolate();

char test[] = "test etasdklfnaskldfnklasdnfklansdfklnasklfnasklndflasdkf";

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

}

void init(Local<Object> exports) {

NODE_SET_METHOD(exports, "hello", Method);

}

NODE_MODULE(NODE_GYP_MODULE_NAME, init)

} // namespace demo

우선 핵심만 간단히 보자면,

NODE_MODULE 로 모듈을 외부에 선언 하는 것인데 이 선언 문이 있어야만, 외부에서 가져다 쓸수 있다. 그리고 이 선언문은 끝에 ;를 빼야한다.

그리고 그안에 넣는 init함수는 반드시

void Initialize(Local<Object> exports); 이런 형태를 띄어야 한다.

즉 Initialize이름은 바뀔수 있지만 리턴 형태나 인자 형태는 바뀌면 안된다.

그리고

저 함수안에..

void init(Local<Object> exports) {

NODE_SET_METHOD(exports, "hello", Method);

}

이런식으로 내가 제작한 함수를 모듈에 포함시킨다.

당연히 여러개도 포합 시킬수 있다.

이런 형태를 꼭 지켜줘야만 한다.

혹시 jni를 제작해 보거나 리눅스 드라이버를 제작해 봤다면 이해되는 부분일 것이다.

아무튼 그런 설명은 제외하고.. 어서 빨리 hello world를 찍자.

4. configure 하기

우선 프로젝트폴더로 가서

node-gyp configure 라고 명령을 내리면 된다.

하... 근데.. 이제 부터가 진짜 어렵다.

나는 windows 환경에서 이 작업을 진행 했는데..

왠만하면 리눅스에서 하는게 속편하다.

진짜 토나오도록 잘 안된다.

아무튼 나왔던 잇슈 사항을 하나씩 나열 하겠다.

우선 node-gyp라는 도구는 두가지 작업 환경을 구축해야하는데..

하나는 파이썬이고, 다른 하나는 비쥬얼스튜디오 이다.

안그러면, node-gyp를 실행하면 파이썬이 없다고 계속 오류를 내뿜는다.

그것도 영어라, 그냥 읽기도 싫은데.. 아무튼 그렇다.

에러 메세지가 대략 이렇다.

gyp ERR! configure error

gyp ERR! stack Error: Can't find Python executable "C:\Users\user\.windows-build-tools\python27\", you can set the PYTHON env variable.

gyp ERR! stack at PythonFinder.failNoPython

우선 이것을 해결하는 방법이 엄청 많은 것들이 있는데.

대표적으로

npm --add-python-to-path='true' --debug install --global windows-build-tools

위방법이다.

파이썬을 패쓰에 추가 하라는 것과, windows-build-tools를 설치하라는 명령어 인데.

위 명령어를 내리면 파이썬과, 비쥬얼스튜디오 2015 프레임웤이 설치된다.

더이상 저 메세지가 안나올 수도 있고 나올수도 있다.

나는 나왔다.

그래서 다음 방안으로 파이썬을 그냥 수동으로 설치했다.

절대 3.0 이상의 버전을 설치하면 안된다고 한다.

2.x 버전을 설치하라고 해서 2.7을 설치 했다.

그리고 나서 해봤는데도 에러는 사라지지 않았다.

그래서 "you can set the PYTHON env variable." 라는 메세지를 보고..

고급 설정으로가서 path 설정에서, PYTHON 패쓰를 잡고,

해봤는데 안된다..

모듈 뻑나서 Node.js다시 설치해보고.. 돌고 돌아 성공한 방법이..

커맨드 창에다가..

set PYTHON=C:\Users\user\.windows-build-tools\python27\python.exe

라고 명령을 내렸더니 해결됐다.

실행 파일까지 패쓰에 넣어서 PYTHON을 설정해주니 에러메세지가 사라졌다.

그리고..

node-gyp configure 라고 명령을 내렸다!!

하.. 또 다른 에러가 나온다.

-----------------------------------------------------------------------

if not defined npm_config_node_gyp (node "C:\ProjectWork\NodeJs\node_modules\npm\node_modules\npm-lifecycle\node-gyp-bin\\..\..\node_modules\node-gyp\bin\node-gyp.js" ) else (node "C:\ProjectWork\NodeJs\node_modules\npm\node_modules\node-gyp\bin" )

module.js:549

throw err;

^

Error: Cannot find module 'C:\ProjectWork\NodeJs\node_modules\npm\node_modules\node-gyp\bin'

at Function.Module._resolveFilename (module.js:547:15)

at Function.Module._load (module.js:474:25)

at Function.Module.runMain (module.js:693:10)

at startup (bootstrap_node.js:188:16)

at bootstrap_node.js:609:3

-------------------------------------------------------------------------------

위에것을 해결하기위해.. npm_config_node_gyp 라는 놈을 열심히 설정해보고 구글링도 해봤는데. 영 답이 안나왔다.

아무튼 npm_config_node_gyp 를 설정하면 되는가 싶어서 설정 해봤더니.. 위에 else 부분에 내가 적용한 내용이 나온다는 것을 알아 냈다...

그래서 혹시나 하고..

set npm_config_node_gyp=C:\ProjectWork\NodeJs\node_modules\npm\node_modules\node-gyp\bin\node-gyp.js

라고 했더니 그뎌!! 동작했다!

역사적인 순간

 

5. build 하기

node-gyp build

명령을 내리면 된다.

나는 문법 적인 오류로 인해, 여러곳을 수정했다.

그리고 여기서 파이썬이 없다는 오류가 사실 났었는데.

그것은 위에 서술한.

set PYTHON=C:\Users\user\.windows-build-tools\python27\python.exe

이 방법으로 해결했다.

이 과정이 끝나면

프로젝트 폴더/build/Release/hangleModule.node

파일이 생긴다.

6. 실행하기.

나는 app.js 파일을 하나 만들었고..

그안에 코드 내용은...

const addon = require('./build/Release/hangleModule.node');

console.log(addon.hello());

이렇게 넣었다

그리고 결과..

test etasdklfnaskldfnklasdnfklansdfklnasklfnasklndflasdkf

라는 문구가 출력되었다.

hello wolrd를 출력해야하는데..

분노에 차서 그만 저런 문구가 출력되었다.

맺으며.

우선 여기까지 되면 모듈을 하나 만들고, 그 모듈에서 정의한 함수를 불러다 쓸 수 있는 기본이 된 것입니다.

그다음 이런 기능 관련된 API들이 있고, 속도를 더 올리기 위한 모듈을 사용하는 부분도 있습니다.

그건 차차 하면 될 것 가고.. 저도 오늘은 위 코드를 쭉 봐보고.. 내가 한 것들이 무엇인지 정리하는 시간을 가져야 할 것 같습니다.

분명 제가 겪은 문제 말고도 다른 문제가 많을 것입니다.

구글과 함께 해결해 봅시다.

정말 첫 환경 구축은 몇년을 해도 너무 어렵습니다.

'개발 > Node.JS' 카테고리의 다른 글

비슷한 문자 찾아내는 Node.js C++ 모듈  (0) 2020.02.07
Node.js C++ 모듈 디버깅하는 법  (0) 2020.02.07

FFmpeg 라이브러리를 참조하는 플레이어를 만들때..

 

package net.jbong.FFmpegBasic;

import android.graphics.Bitmap;

public class FFmpegInterface {
    public static native int initBasicPlayer();
 public static native int openMovie(String filePath);
 public static native int renderFrame(Bitmap bitmap);
 public static native int getMovieWidth();
 public static native int getMovieHeight();
 public static native void closeMovie();

이와 같은 내용의 java파일을 class 파일로 만든 후.

javah로 jni 형태의 헤더 파일을 만드려 할때.

다음과 같은 문제가 나왔다.

 

Error: cannot access android.app.Activity
  class file for android.app.Activity not found

 

즉 위에 import android.graphics.Bitmap;이놈이 문제

 

이놈을 빼버리고 javah 하면 되지만.

문제는 public static native int renderFrame(Bitmap bitmap);

여기에 Bitmap class가 쓰여 반드시 import 해야 되는 상황.

 

우선 작업 환경이.

Windows와 우분투 병행 작업 환경 이기 때문에.

 

Vm-ware에

Windows의 C:\android\adt-bundle-windows-x86_64-20131030\sdk\platforms\android-19 폴더를공유한다.

 

그럼 vm-ware 우분투에서 /mnt/hgfs/android-19를 마음대로 드나 들수있다.

 

 

우선 class 파일을 만들기 위해.

 

java 파일이 있는 폴더로 가서. 다음과 같이 입력.

 

javac -cp /mnt/hgfs/android-19/android.jar FFmpegInterface.java

FFmpegInterface.java는 내가 만든 파일이고.

-cp의 뜻은 android.jar를 참조해서 컴파일(?)하라는 것이다.

 

그럼 class가 만들어 진다.

-cp를 안하면 컴파일 안된다.

 

또는 이클립스등을 이용해서 class를 만들면 된다.

 

 

그후, JNI 방식대로 폴더를 만들고. class를 파일을 넣고..

 

javah -classpath ./ -bootclasspath /mnt/hgfs/android-19/android.jar -jni net.jbong.FFmpegBasic.FFmpegBasic

 

입력.

 

 

classpath : class파일이 잇는 곳

bootclasspath : android.jar를 참조(?)하샘.

-jni : jni 형태로 해더 파일 만들어주세요.

net.jbong.FFmpegBasic.FFmpegBasic : 패키지 경로..

 

이러면 헤더 파일 만들어진다.

 

검색해 보니깐.. 없는 것 같아서 적어놨음.

나는 VMware와

V-box를 둘다 쓰는데..

 

둘다 에러가 났다..

둘다 부팅이 안된다.

 

우선 vmware 에러는

 

Transport (VMDB) error -44: Message

 

메세지를 뿜었다.

 

그래서 해결 방법을 보니..

 

http://hummingbird.tistory.com/4415

VMware 오류 메시지 : Transport (VMDB) error -44: Message 해결 방법

데스크탑 가상화 솔루션으로 유명한 VMware Workstation 제품을 이용하다가 특정 스냅샷(Snapshot)으로 복원을 시도하거나 생성된 이미지를 이...

hummingbird.tistory.com

 

에 나와있는데..

저기에서 말하는 것은..

서비스 항목 중 "VMware Authorization Service"를 실행 하라는 것이다.

​ 근데.. 난 재실행이 안되었다.

파일 자체가 없는 것 같았다..

그래서 어찌 하지 고민하다가..

 

내가 설치 한것은

VMware-workstation-full-9.0.2-1031769

인데.. 다시 설치 프로그램을 실행 시키고..

 

 

 

저기 repair 라고 된것을 선택 하고  Next 했더니..

한 10분 뭔짓을 하더니..

복구가 완료 됬다고 한다..

 

그리고 다시 실행 해보니 잘 되었다...

 

누군가에겐 큰 도움이 된다는 것을 알기에..!

방금 포스트 쓴.. VMware 에러는 해결 했는데..

ACPI PCC Probe Failed

 라는 메세지를 뿜고 죽는 V-Box는.. 살려 보려 했으나 살려 지지가 않아서.

 

복원을 시도 했는데.. 그러던  중 원인을 알았다.

 

우선 저 메세지는 커널단에 오류인데..

검색한 해결책 대부분(제대로된 해결책도 없다) 그래픽 카드 드라이버 하고 연관된 이야기가 나왔다..

하지만 v-box하고 연관된 해결책은 나오지가 않았다..

 

아무튼 원인은 v-box 이미지에서 설정한 하드 용량이 50gb인데..

그게 꽉차서 나는 오류 였다..

 

어떻게 알아 냈냐면..

기존 이미지를 복원 하고..

그 이미지에 진행 하던 프로젝트 파일을 옮기는데 똑같은 증상이 나와서..

혹시나 하드용량 문제 인가??

했는데..

 

아니다 다를까.

 

부팅 안되던 이미지도..

x-windows로 부팅 안하고.. 그냥 터미널로 부팅해서.

파일들은 지우니깐..

다시 정상 동작 했다..

 

아무튼 해결 방법은..

터미널로 부팅해서

파일을 지우고..

 

정상 부팅 하게 만든다음에  (우선 이것만 해도 해결은 된다. 하지만 더 용량을 늘려서 사용하고 싶으면) vmdx 파일을 VBoxManage 유틸을 통해 용량을 늘리면 된다..

 

아무튼 해결 되어서 기쁘다..

윈도우 10에서 v-box 리눅스로 ping은 되는데..

반대로는 안보내지는 상황..

혹시나 arp 테이블도 지워 보고.. 이것 저것 해봐도 안됨.

 

원인은 방화벽..

 

위에 가상 컴퓨터 모니터링( 에코 요청 -ICMPIPv4-IN) 부분을 활성화 시켜 주면..

핑 잘간다.

분명 잘 동작했던 것 같은데..

언제 부턴가 force_download 함수가 동작을 잘 하지 않았다...

진짜 10시간을 넘게 디버깅을 했는데.

 

결국 원인은..

파일을 업로드하는 것은 정상 동작 하는데..

 

다운 받으면, 맨앞에

바이너리 값으로 0A 0D 0A가 붙어서..

해더 파일이 깨져서 이미지가 나오지 않는 것 이었다.

 

번지수  : 원본파일  다운파일

00000000: FF           0A   <-- 쓰레기 값?

00000001: D8           0D

00000002: FF           0A

00000003: DB          FF

00000004: 00           D8

00000005: 43           FF

00000006: 00          DB

00000007: 03          00

00000008: 02          43

00000009: 02          00

0000000E: 03          02

0000000F: 03          02

 

 

저것은 아스키 코드로 CR LF 에 해당하는 문자들이다..

 

도대체 저게 왜 찍혀 나오는 거지...

진짜 코드 싹 뒤져 가면서 쫒아 갔는데..

아무곳도~ 저 문자를 넣는 부분이 없엇다..

 

그러다.. 구굴링중..

함수 두개를 발견..

 

ob_clean();

flush();

 

출력 버퍼를 지워 주는 함수 인데..

혹시나 ~ 하면서.. 사용 해 봤더니 잘된다 ㅠ.ㅠ

 

 

아무튼 나는 이렇게 해결했다.

 

download_helper.php를

MY_download_helper.php로 오버 로딩 시켰고.

 

내용은 그냥 download_helper.php에 있는 걸 복사하고..

 

마지막에.

 

else

{

header('Content-Description: File Transfer');

header('Content-Type: "'.$mime.'"');

header('Content-Disposition: attachment; filename="'.$filename.'"');

header("Content-Transfer-Encoding: binary");

header('Expires: 0');

header('Cache-Control: must-revalidate, post-check=0, pre-check=0');

header('Pragma: no-cache');

header("Content-Length: ".$filelen);

 

 

 

}

 

ob_clean();

flush();

exit($data);

 

 

이렇게 두개를 추가하니~

CR LF에 해당하는 값이 사라지고..

정상적으로 이미지 파일 등등이 출력 되었다.

 

 

소수에게만 필요한 정보겠지만..

누군가의 10시간 노가다 방지를 위하여 썼습니다.

이글을 쓸때 상당히 열받아 있었던 상태-_-;로 매우 감정적으로 글을 썻다.

 

STM 칩을 통해서 개발할 일이 있어서 IAR Embedded Workbench IDE를 3달정도 사용해 봤다...

단순 3달이 아니라.. 하루에 10시간 이상 3달이다..

결론 부터 말하면 정말 지상 최악의 편집툴이다.

 

엄청나게 좋은 기능들이 많고, 좋은 디버깅 기능을 제공한다.

진짜 정말 정말 좋은 기능이 많은데..

 

내가 최악이라고 결론을 내리는 이유는 하나이다.

 

편집 부분이 진짜 최악이다. 차라리 메모장이 날 정도이다.

진짜 최악 중에 최악이며 쓰레기다.

 

나는 비쥬얼 스튜니오, 이클립스, 메모장, 압타나, VI 에디터 등등등.. 그냥 가리지 않고 쓰고.

단축키도 필요한 것 위주로 외어서 그냥 바로 바로 쓰는 타입니다.

 

근데 진짜.. 이 IAR에서 제공하는 Workbench IDE라는 놈은 지상 최악에 물건이다.

 

c파일들을 열어 놓고, 수정을 쭉하고..

컴파일 다하고 디버깅으로 들어가면, 또 파일들을 새롭게 열고..

새롭게 편집 창들을 크기도 조절 다 해야한다..

 

근데 디버깅 중에.. 앗 이 부분을 고쳐야지 하고.. 고치고.. 다시 컴파일을 하면 열어논 파일의 순서는 다 틀어지고...

 

또한 디버깅에서의 활성화 파일이 A라면, 디버깅을 끄고 나서는 활성화된 파일이 C가 되고..

필요해서 열어논 파일은 이유는 모르겠지만 닫혀있다..

 

진짜 사용하면서 욕이 계속 나왔다.

 

아니.. 프로젝트안에서 편집할 파일이 100개가 넘어 가는데..

이건뭐 디버깅만 하고 끄면 열어논 파일들이 랜덤하게 닫혀 있고..

내가 활성화된 부분도 아니고...

 

3달 정도 사용하다가 결론은 이 쓰레기는 절대 안쓴다는거다.

 

물론 그외 기능은 정말 좋다.. 디버깅도 편하고...

 

그리고, STM칩에 Sleep 기능을 가지고 코딩하다보면...

디버깅 부분에서 경고창이 대략 4개 정도 뜨는데.. (J-Link 통신이 안된다고..)

근데 끌때마다.. 데드락 비슷한 형상이 일어난다..

즉 슬립 들어 갈때 마다.. 경고창 닫는 시간이 10초는 걸린다.

 

진짜 말이 10초지.. 보통 디버깅을 못해도 200번은 하는데..

그때마다, 10초씩 기다리는 건 진짜 개발 시간 지연에..

 

거기다.. 아까 말한 편집 활성화된 파일들이 지맘대로 닫히고..

뒤바뀌고.. 다시 열고 하는 시간을 따지면..

 

진짜 시간도 많이 잡아 먹고...

성질은 성질대로 나고..

사람 성격 버리는 개쓰레기 편집툴이다..

 

또한 보통 개발자들은 듀얼 모니터를 쓰는데..

이건 편집 윈도우들을 분리를 할 수가 없다..

그래서, 듀얼 모니터로 각각 보려면..

전체 화면이 아닌 그냥 쭈욱 길게 늘어나게 해서..

두 모니터를 차지하게 하고.. 그 안에서 윈도우를 만들어..

크기를 모니터에 맞게 정렬을 해야한다..

그러다.. 어떤 창을 추가 하거나.. 디버깅 하고 싶은 것를 하나더 넣으면

창크기를 또 조절해야 하며..

한쪽 창크기를 늘리면 다른 창크기들도 다 일일이 조절해줘야한다.

진짜 차라리 vi 에디터가 1억배 난것 같다.

 

 

하지만.. 위 단점만 뺀다면 매우 좋은 개발 툴이긴 하다.

근데 단점이 너무 최악이다.. 

 

혹시 내가 잘 못 사용 하는 거면 누가 해결 방법좀 알려주면 좋겠다.

해결 하고 싶어서 일일이 메뉴를 다 눌러 봤는데 해결 방법이 나오지를 않는다.

+ Recent posts