编写应用时,我们常会遇到这样的烦恼:明明有自己独特的业务需求,却苦于找不到合适的类库。这确实让人挺头疼的,感觉就像在黑暗中摸索,却怎么也找不到那灯的开关。不过,别担心,有一些方法可以帮助我们破解这类难题。
找不到类库的苦恼
编写程序时,这类问题颇为常见。许多程序员投入大量时间,试图构思出独特的业务应用需求,但最终却发现市场上的现有类库无法满足他们的需求。遇到这种情况,开发进度便会受到阻碍,时间和精力也会被大量浪费。在团队协作的环境下,若项目需要交付,找不到合适的类库将影响整个团队的进度安排。因为每个人的工作都是项目整体的一部分。
这也可能带来额外成本的增长。比如,若找不到合适的类库,就可能得多花时间重构代码逻辑;更严重的是,可能得从零开始开发。这无疑是对人力和时间成本的双重增加,给项目开发带来了不小的压力。
npm install -g cmake-js
node-gyp简介
首先,让我们来了解node-gyp。这是一个在开发界颇负盛名的跨平台编译工具。对那些有编写经验的人来说,它就像一位并肩作战的老朋友。在进行特定编译任务时,比如编写sass并安装了node-sass,我们不得不依赖node-gyp来完成编译。node-gyp与gyp在本质上颇为相似,可以看作是增强编译功能的工具,它在编程过程中扮演着一定的助手角色。
在使用node-gyp的过程中,难免会遇到一些问题。这些问题可能出现在配置阶段,也可能发生在编译阶段。这些问题解决起来可能颇为棘手,因为它们与整个编译流程和系统环境的适配等多重因素相关。对于技术能力稍逊一筹的开发者来说,这无疑是一个不小的挑战。
cmake-js的特点
cmake-js这个名字让人一眼就能联想到cmake,确实,它就是基于CMake构建系统的工具。这个工具非常实用,和node-gyp一样,它也支持跨平台编译。在实际使用中,cmake-js在安装和使用上相较于node-gyp有着明显的优势。作为开发者,我们都希望工具越简单越好,而cmake-js在这方面做得相当不错。
安装过程简单,直接利用npm即可完成。虽然安装过程可能耗时较长,但确实方便快捷。这样的安装流程在开发阶段能节省大量时间,使开发者能迅速投入到编译和扩展等任务中。对于对时效性要求极高的项目来说,这一点尤为关键。
cmake的安装操作
安装CMake是关键步骤之一。若选用了安装包,过程大致顺利,操作简便。但若使用压缩包,事情会复杂些。解压后,进入文件夹,内容相似,但版本不同,也可能有细微差别。这时,需复制文件夹路径,进行选择。若发现缺少预期输出,可能是环境变量路径设置错误或环境变量未激活。若环境变量未激活,有时需重启电脑才能解决。这些看似简单的操作实则至关重要,每一步都影响编译的后续步骤能否顺畅进行。
在软件公司的开发环境中,新来的程序员可能会对这些操作不太了解。一旦在这个环节出现问题,他们可能会寻求经验丰富的开发人员的帮助。如果问题不能迅速得到解决,这同样会影响到项目的正常开发进度。
npm init
vs编译器的版本要求
在使用vs编译器时,版本选择至关重要。必须确保vs编译器的版本与已安装的cmake版本相吻合。尽管市面上的常见VS版本理论上都能兼容,但实际操作中仍需核实。如何核实?这里有一个小技巧:打开cmake的bin目录,运行cmake-gui.exe,接着在下拉列表中进行查看。虽然这个过程看起来简单,但若在此处出错,后续的编译过程将无法顺利进行。
"dependencies": {
"node-addon-api": "^3.0.0"
},
"cmake-js": {
"runtime": "node",
"runtimeVersion": "12.16.3",
"arch": "x64"//64位
}
大型项目开发中,不同模块往往由不同人员负责。若负责人员未留意版本匹配问题,可能导致项目编译失败。此时,需重新调整项目环境及模块间兼容性,过程繁琐。
npm i
最后的编译与调用
完成所有前期准备工作后,便进入了至关重要的编译和调用环节。前期的工作,就好比是为后续铺路,而此刻正是检验前期成果的时刻。完成文件创建和代码编写后,便可以开始编译操作。打开命令提示符,切换至工作目录,输入指定命令,耐心等待执行结束。若一切顺利,工作目录中便会新增一个名为“build”的文件夹,其中包含VS项目文件,同时还会生成一个名为“aaaa.node”的文件,这就是编译生成的扩展文件。
project (aaaa)
cmake_minimum_required(VERSION 3.16)
include_directories(${CMAKE_JS_INC})
file(GLOB SOURCE_FILES "*.cc")
add_library(${PROJECT_NAME} SHARED ${SOURCE_FILES} ${CMAKE_JS_SRC})
set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "" SUFFIX ".node")
target_link_libraries(${PROJECT_NAME} ${CMAKE_JS_LIB})
# 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})
target_link_libraries(${PROJECT_NAME} ${CMAKE_JS_LIB})
# Define NAPI_VERSION
add_definitions(-DNAPI_VERSION=3)
之后便要涉及到使用这个扩展了。需要编写一个JS文件,类似于示例中的a.js,接着进行调用。在此过程中,可以打开Build文件夹,用VS编辑项目文件,进行修改或重新编译等操作,这就像为程序注入新的活力。但需注意的是,尽管扩展开发看似不复杂,但它的API却相当丰富,若要开发扩展,就必须认真学习并深入研究这些API。
编写应用时,你是否曾遭遇过找不到合适的类库的困境?又或是自己在构建解决方案时遇到了重重难题?若你有独到的经验或见解,不妨在评论区与我们分享。同时,也期待大家能点赞并转发这篇文章。
using namespace std;
static napi_value MyFun(napi_env env, napi_callback_info info) {
napi_status status;
napi_value str;
status = napi_create_string_utf8(env, "mytest", 6, &str);
assert(status == napi_ok);
return str;
}
static napi_value YouFun(napi_env env, napi_callback_info info) {
napi_status status;
size_t argc = 2;
napi_value args[2];
status = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
size_t strleng;
napi_get_value_string_utf8(env, args[0], 0, 0, &strleng);
string p1;
p1.reserve(strleng + 1);
p1.resize(strleng);
status = napi_get_value_string_utf8(env, args[0], &p1[0], p1.capacity(), nullptr);
napi_get_value_string_utf8(env, args[1], 0, 0, &strleng);
string p2;
p2.reserve(strleng + 1);
p2.resize(strleng);
status = napi_get_value_string_utf8(env, args[1], &p2[0], p2.capacity(), nullptr);
napi_value v;
string dest = "p1:"+ p1 + "p2:" + p2;
napi_create_string_utf8(env,dest.c_str(), strlen(dest.c_str()+1), &v);
return v;
}
{ name, 0, func, 0, 0, 0, napi_default, 0 }
static napi_value Init(napi_env env, napi_value exports) {
napi_status status;
napi_property_descriptor mytest = DECLARE_NAPI_METHOD("mytest", MyFun);
status = napi_define_properties(env, exports, 1, &mytest);
napi_property_descriptor youtest = DECLARE_NAPI_METHOD("youtest", YouFun);
status = napi_define_properties(env, exports, 1, &youtest);
assert(status == napi_ok);
return exports;
}
NAPI_MODULE(NODE_GYP_MODULE_NAME, Init)