C++ 中的 NAPI 本机模块正在部分执行(包括 std::thread)
NAPI native module in C++ is executing partially (Included std::thread)
我用 NAPI 编写的 Node-js 本机模块正在部分执行。
我在其中使用了多个线程。
虽然 运行 模块有时会打印线程已启动但有时它不会。
而且无论哪种方式,模块都不会到达 C++ 代码的末尾。
我已经将我的 C++ 代码作为一个独立的应用程序进行了尝试,并且工作正常,没有任何警告或错误。
我在 "CMakeList.txt"
中开启了异常处理
C++ 17 支持开启,因为我使用的是 std::filesystem,它工作正常。
我在 "CMakeList".
中使用 find_package(需要线程)
file CMakeList.txt=>
cmake_minimum_required(VERSION 3.15)
# Name of the project (will be the name of the plugin)
project (addon)
set(CMAKE_CXX_STANDARD 17)
# Don't add this line if you will try_compile with boost.
set(CMAKE_CXX_STANDARD_REQUIRED ON)
option(USE_CXX_EXCEPTIONS "Enable C++ exception support" ON)
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
# Essential include files to build a node addon,
# you should add this line in every CMake.js based project.
include_directories(${CMAKE_JS_INC})
# Declare the location of the source files
file(GLOB SOURCE_FILES "cppsrc/*.cpp" "cppsrc/*.h")
# This line will tell CMake that we're building a shared library
# from the above source files
# named after the project's name
add_library(${PROJECT_NAME} SHARED ${SOURCE_FILES} ${CMAKE_JS_SRC})
# This line will give our library file a .node extension without any "lib" prefix
set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "" SUFFIX ".node")
# Essential library files to link to a node addon,
# you should add this line in every CMake.js based project.
target_link_libraries(${PROJECT_NAME} ${CMAKE_JS_LIB} ${CMAKE_THREAD_LIBS_INIT})
# Include N-API wrappers
execute_process(COMMAND node -p "require('node-addon-api').include"
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE NODE_ADDON_API_DIR
)
string(REPLACE "\n" "" NODE_ADDON_API_DIR ${NODE_ADDON_API_DIR})
string(REPLACE "\"" "" NODE_ADDON_API_DIR ${NODE_ADDON_API_DIR})
target_include_directories(${PROJECT_NAME} PRIVATE ${NODE_ADDON_API_DIR})
file package.json=>
{
"name": "test-addon",
"version": "1.0.0",
"description": "",
"author": "",
"license": "ISC",
"scripts": {
"install": "cmake-js compile"
},
"cmake-js": {
"runtime": "electron",
"runtimeVersion": "5.0.5",
"arch": "x64"
},
"devDependencies": {},
"dependencies": {
"cmake-js": "^5.3.0",
"node-addon-api": "^1.6.3"
}
}
the c++ code which is executing partially =>
while (file != filePaths.end()) {
start = timeStamp();
cout << "\n" << "File: " << *file << " \n";
//process Data
pres.readRawDataList(*file);
for (int i = 0; i < hwGuess; i++) {
begint = (i * pres.rawDataList.size()) / hwGuess;
endt = (i + (size_t)1) * pres.rawDataList.size() / hwGuess;
CthreadObj[i].rawData.reserve(pres.rawDataList.size() / hwGuess);
CthreadObj[i].rawData.insert(CthreadObj[i].Pcomparison::rawData.begin(), pres.rawDataList.begin() + begint, pres.rawDataList.begin() + endt);
threads.push_back(thread([&]() { ExpSub(CthreadObj[i], PthreadObj[i]); }));
}
for (int j = 0; j < hwGuess; j++) {
cout<<"join total 4 threads\n";
threads.at(j).join();
}
cout<<hwGuess<<" \n";
cout<<"thread Ends \n";
pfile.writeFile(pres.results, "cppsrc/Output/0.txt");
pres.rawDataList.clear(); pres.rawDataList.shrink_to_fit();
pres.results.clear(); pres.results.shrink_to_fit();
//Processed
cout<<"While ends \n";
file++;
funtion ExpSub=>
ExpSub(Pcomparison& ThreadObjC, Ppattern& ThreadObjP) {
vector<string>::iterator rawIt;
ThreadObjC.lowerCaseRawData();
cout<<"Inside Thread\n";
ThreadObjC.extractEmailAndPassword(":");
ThreadObjC.extractEmailNamesAndWebsites();
hwGuess value is 4
结果应该是上面代码中的打印消息"While ends"
这应该每次都不会随机发生(检查它随机执行的图像 "thread inside line")。
[在此处输入图片描述][1]
https://i.stack.imgur.com/55TGy.png
C++ 中的 Lambda 函数在 node.js N-API 中无法完美运行。所以最好在你的 C++ 代码中忽略 lambdas。
或者你可以这样做
threads.push_back(thread(&class_namespace::ExpSub, ref(CthreadObj[i]), ref(PthreadObj[i])));
并注意您需要使用 ref() 来传递引用的参数。
我用 NAPI 编写的 Node-js 本机模块正在部分执行。
我在其中使用了多个线程。
虽然 运行 模块有时会打印线程已启动但有时它不会。
而且无论哪种方式,模块都不会到达 C++ 代码的末尾。
我已经将我的 C++ 代码作为一个独立的应用程序进行了尝试,并且工作正常,没有任何警告或错误。
我在 "CMakeList.txt"
中开启了异常处理
C++ 17 支持开启,因为我使用的是 std::filesystem,它工作正常。
我在 "CMakeList".
file CMakeList.txt=>
cmake_minimum_required(VERSION 3.15)
# Name of the project (will be the name of the plugin)
project (addon)
set(CMAKE_CXX_STANDARD 17)
# Don't add this line if you will try_compile with boost.
set(CMAKE_CXX_STANDARD_REQUIRED ON)
option(USE_CXX_EXCEPTIONS "Enable C++ exception support" ON)
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
# Essential include files to build a node addon,
# you should add this line in every CMake.js based project.
include_directories(${CMAKE_JS_INC})
# Declare the location of the source files
file(GLOB SOURCE_FILES "cppsrc/*.cpp" "cppsrc/*.h")
# This line will tell CMake that we're building a shared library
# from the above source files
# named after the project's name
add_library(${PROJECT_NAME} SHARED ${SOURCE_FILES} ${CMAKE_JS_SRC})
# This line will give our library file a .node extension without any "lib" prefix
set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "" SUFFIX ".node")
# Essential library files to link to a node addon,
# you should add this line in every CMake.js based project.
target_link_libraries(${PROJECT_NAME} ${CMAKE_JS_LIB} ${CMAKE_THREAD_LIBS_INIT})
# Include N-API wrappers
execute_process(COMMAND node -p "require('node-addon-api').include"
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE NODE_ADDON_API_DIR
)
string(REPLACE "\n" "" NODE_ADDON_API_DIR ${NODE_ADDON_API_DIR})
string(REPLACE "\"" "" NODE_ADDON_API_DIR ${NODE_ADDON_API_DIR})
target_include_directories(${PROJECT_NAME} PRIVATE ${NODE_ADDON_API_DIR})
file package.json=>
{
"name": "test-addon",
"version": "1.0.0",
"description": "",
"author": "",
"license": "ISC",
"scripts": {
"install": "cmake-js compile"
},
"cmake-js": {
"runtime": "electron",
"runtimeVersion": "5.0.5",
"arch": "x64"
},
"devDependencies": {},
"dependencies": {
"cmake-js": "^5.3.0",
"node-addon-api": "^1.6.3"
}
}
the c++ code which is executing partially =>
while (file != filePaths.end()) {
start = timeStamp();
cout << "\n" << "File: " << *file << " \n";
//process Data
pres.readRawDataList(*file);
for (int i = 0; i < hwGuess; i++) {
begint = (i * pres.rawDataList.size()) / hwGuess;
endt = (i + (size_t)1) * pres.rawDataList.size() / hwGuess;
CthreadObj[i].rawData.reserve(pres.rawDataList.size() / hwGuess);
CthreadObj[i].rawData.insert(CthreadObj[i].Pcomparison::rawData.begin(), pres.rawDataList.begin() + begint, pres.rawDataList.begin() + endt);
threads.push_back(thread([&]() { ExpSub(CthreadObj[i], PthreadObj[i]); }));
}
for (int j = 0; j < hwGuess; j++) {
cout<<"join total 4 threads\n";
threads.at(j).join();
}
cout<<hwGuess<<" \n";
cout<<"thread Ends \n";
pfile.writeFile(pres.results, "cppsrc/Output/0.txt");
pres.rawDataList.clear(); pres.rawDataList.shrink_to_fit();
pres.results.clear(); pres.results.shrink_to_fit();
//Processed
cout<<"While ends \n";
file++;
funtion ExpSub=>
ExpSub(Pcomparison& ThreadObjC, Ppattern& ThreadObjP) {
vector<string>::iterator rawIt;
ThreadObjC.lowerCaseRawData();
cout<<"Inside Thread\n";
ThreadObjC.extractEmailAndPassword(":");
ThreadObjC.extractEmailNamesAndWebsites();
hwGuess value is 4
结果应该是上面代码中的打印消息"While ends" 这应该每次都不会随机发生(检查它随机执行的图像 "thread inside line")。 [在此处输入图片描述][1]
https://i.stack.imgur.com/55TGy.png
C++ 中的 Lambda 函数在 node.js N-API 中无法完美运行。所以最好在你的 C++ 代码中忽略 lambdas。 或者你可以这样做
threads.push_back(thread(&class_namespace::ExpSub, ref(CthreadObj[i]), ref(PthreadObj[i])));
并注意您需要使用 ref() 来传递引用的参数。