NodeJS C++插件开发(四) - Visual Studio Code调试C++插件教程
如需转载请标明出处
QQ技术交流群:129518033
文章目录
相关阅读:
NodeJS C++插件开发(一) - 简介
NodeJS C++插件开发(二) - 示例代码hello world
NodeJS C++插件开发(三) - 调试概述
前言
在NodeJS C++插件开发(三) - 调试概述中介绍了几种NodeJS C++插件的调试方法,本文将以第三方库的C++插件的代码示例详细介绍如何使用Visual Studio Code调试C++插件。
1. 安装必要环境
- 安装NodeJS(14.16.0)
- 安装node-gyp依赖-python
- 安装node-gyp依赖-编译器
windows:Microsoft Visual C++ (MSVC) (Visual Studio 2019)
linux: gcc g++ gdb make - 安装node-gyp (npm i -g node-gyp)
- 安装 Visual Studio Code
- 安装 Visual Studio Code调试插件C/C++ extension for VS Code
2. 测试代码
目录结构:
code
+--- .vscode
| +--- launch.json
+--- addon.cpp
+--- binding.gyp
+--- common.h
+--- index.js
+--- thirdlib
| +--- CMakeLists.txt
| +--- myadd.cc
| +--- myadd.h
- 第三方库代码
myadd.h
// myadd.h
#if defined(_WIN32)
#define DLL_EXPORT __declspec(dllexport) ///< define DLL_EXPORT windows
#else
#define DLL_EXPORT __attribute__((visibility("default"))) ///< define DLL_EXPORT unix
#endif
int DLL_EXPORT myAdd(int x, int y);
myadd.cc
// myadd.cc
#include "myadd.h"
int myAdd(int x, int y)
{
return x + y;
}
- NodeJS C+++插件代码
common.h
#include <js_native_api.h>
// node-v12.13.0/test/js-native-api/common.h
// Empty value so that macros here are able to return NULL or void
#define NAPI_RETVAL_NOTHING // Intentionally blank #define
#define GET_AND_THROW_LAST_ERROR(env) \
do { \
const napi_extended_error_info *error_info; \
napi_get_last_error_info((env), &error_info); \
bool is_pending; \
napi_is_exception_pending((env), &is_pending); \
/* If an exception is already pending, don't rethrow it */ \
if (!is_pending) { \
const char* error_message = error_info->error_message != NULL ? \
error_info->error_message : \
"empty error message"; \
napi_throw_error((env), NULL, error_message); \
} \
} while (0)
#define NAPI_ASSERT_BASE(env, assertion, message, ret_val) \
do { \
if (!(assertion)) { \
napi_throw_error( \
(env), \
NULL, \
"assertion (" #assertion ") failed: " message); \
return ret_val; \
} \
} while (0)
// Returns NULL on failed assertion.
// This is meant to be used inside napi_callback methods.
#define NAPI_ASSERT(env, assertion, message) \
NAPI_ASSERT_BASE(env, assertion, message, NULL)
// Returns empty on failed assertion.
// This is meant to be used inside functions with void return type.
#define NAPI_ASSERT_RETURN_VOID(env, assertion, message) \
NAPI_ASSERT_BASE(env, assertion, message, NAPI_RETVAL_NOTHING)
#define NAPI_CALL_BASE(env, the_call, ret_val) \
do { \
if ((the_call) != napi_ok) { \
GET_AND_THROW_LAST_ERROR((env)); \
return ret_val; \
} \
} while (0)
// Returns NULL if the_call doesn't return napi_ok.
#define NAPI_CALL(env, the_call) \
NAPI_CALL_BASE(env, the_call, NULL)
// Returns empty if the_call doesn't return napi_ok.
#define NAPI_CALL_RETURN_VOID(env, the_call) \
NAPI_CALL_BASE(env, the_call, NAPI_RETVAL_NOTHING)
#define DECLARE_NAPI_PROPERTY(name, func) \
{ (name), NULL, (func), NULL, NULL, NULL, napi_default, NULL }
#define DECLARE_NAPI_GETTER(name, func) \
{ (name), NULL, NULL, (func), NULL, NULL, napi_default, NULL }
addon.cpp
#include "common.h"
#include <node_api.h>
#include "myadd.h" // function myAdd
static napi_value helloMethod(napi_env env, napi_callback_info info)
{
napi_value result;
NAPI_CALL(env, napi_create_string_utf8(env, "hello world", NAPI_AUTO_LENGTH, &result));
return result;
}
static napi_value addMethod(napi_env env, napi_callback_info info)
{
size_t argc = 2;
napi_value args[2];
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
NAPI_ASSERT(env, argc >= 2, "Not enough arguments, expected 2.");
napi_valuetype valuetype0, valuetype1;
NAPI_CALL(env, napi_typeof(env, args[0], &valuetype0));
NAPI_CALL(env, napi_typeof(env, args[1], &valuetype1));
NAPI_ASSERT(env, valuetype0 == napi_number && valuetype1 == napi_number, "Wrong argument type. Numbers expected.");
int x;
NAPI_CALL(env, napi_get_value_int32(env, args[0], &x));
int y;
NAPI_CALL(env, napi_get_value_int32(env, args[1], &y));
napi_value sum;
NAPI_CALL(env, napi_create_double(env, myAdd(x, y), &sum));
return sum;
}
static napi_value Init(napi_env env, napi_value exports)
{
napi_property_descriptor properties[] = {DECLARE_NAPI_PROPERTY("hello", helloMethod),
DECLARE_NAPI_PROPERTY("add", addMethod)};
NAPI_CALL(env, napi_define_properties(env, exports, sizeof(properties) / sizeof(*properties), properties));
return exports;
}
NAPI_MODULE(NODE_GYP_MODULE_NAME, Init)
- node-gyp源码构建配置文件
{
'targets': [
{
'target_name': 'addon',
'sources': [ 'addon.cpp' ],
'include_dirs':[ 'thirdlib' ],
'libraries':[ '-lmyadd' ],
# 'library_dirs':[ '<(module_root_dir)/thirdlib/bin_win/Debug' ]
'conditions': [
['OS=="win"',{
'library_dirs':[ '<(module_root_dir)/thirdlib/bin_win/Debug' ]
}],
['OS=="linux"',{ 'library_dirs':[ '<(module_root_dir)/thirdlib/bin_unix' ]
}],
['OS=="mac"',{ # not test 'library_dirs':[ '<(module_root_dir)/thirdlib/bin_unix' ]
}]
]
}
]
}
- 测试的js代码
index.js
'use strict';
const addon = require('./build/Debug/addon.node');
console.log('JS output : ',addon.hello()); // hello world
console.log('JS output : ', addon.add(3, 6)); // 3+6=9
3. 编译
3.1 生成第三方库
cd thirdlib
mkdir bin_win
cd bin_win
cmake ..
cmake --build .
3.2 生成debug版本的addon.node
cd code
node-gyp configure build --debug
注意:只有带有调试信息的NodeJS C++插件才能进行源码调试。
4. 配置vscode调试环境
4.1 windows msvc(Visual Studio)
【Run(Ctrl + Shift + D)】-> 【create a launch.json file】-> 【C++ (Windows)】
{
"version": "0.2.0",
"configurations": [
{
"name": "(Windows) 启动",
"type": "cppvsdbg",
"request": "launch",
"program": "C:/Program Files/nodejs/node.exe",
"args": ["${workspaceFolder}/index.js"],
"stopAtEntry": false,
"cwd": "${fileDirname}",
"environment": [],
"console": "externalTerminal"
}
]
}
4.2 linux gcc/g++
【Run(Ctrl + Shift + D)】-> 【create a launch.json file】-> 【C++ (GDB/LLDB)】
{
"version": "0.2.0",
"configurations": [
{
"name": "g++ - 生成和调试活动文件",
"type": "cppdbg",
"request": "launch",
"program": "/usr/local/bin/node",
"args": ["${workspaceFolder}/index.js"],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "为 gdb 启用整齐打印",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
],
"miDebuggerPath": "/usr/bin/gdb"
}
]
}
5. 调试
在vscode中按F5进行调试。
vscode左侧有变量、监视、调用堆栈和断点的信息。
License
License under CC BY-NC-ND 4.0: 署名-非商业使用-禁止演绎
Reference: