首页 > 编程语言 >用Napi编写nodejs Addon并调用dll

用Napi编写nodejs Addon并调用dll

时间:2024-06-12 18:11:28浏览次数:28  
标签:name nodejs void dll DLL EXPORT include Napi

用Napi编写nodejs Addon并调用dll

npdejs调用C++ addon并没有先前那篇随笔那么复杂,这是一篇补充说明:说明如何使用c++项目的include头文件以及lib,dll引入到addon内使用

一、使用VS编写DLL导出项目

  • 步骤1:通过Visual Studio(推荐2019及其以上)新建一个“具有导出项的(DLL)动态链接库”
  • 步骤2:编写代码

必须准守如下规则:

  • 1、所有的dll导出必须在堆空间内,包括struct属性或者class属性(详细看底下代码样例)
  • 2、必须使用dll导出的释放函数进行释放,遵循“谁申请谁释放,申请多少释放多少”
  • 3、只能使用C基础数据类型,不能使用C++类型(例如string,map,vector等)但允许自定义class,属性也必须是C基础数据类型,且准守第1条。
//DllExportTemplate.h
#ifdef DLLEXPORTTEMPLATE_EXPORTS
#define DLL_EXPORT __declspec(dllexport)
#else
#define DLL_EXPORT __declspec(dllimport)
#endif

#include "pch.h"
#include "framework.h"
#include <string>
#include <iostream>
using namespace std;

//释放指针
DLL_EXPORT void freePointer(void* any);
DLL_EXPORT void deletePointer(void* any);
// 导出常量
extern DLL_EXPORT string version = "1.0.0";
// 导出指针
DLL_EXPORT char* getHello();

class DLL_EXPORT People {
public:
    char* name;
    int age;
    People(char* name, int age) {
        this->name = name;
        this->age = age;
    }
    void showInfo() {
        cout << this->name << " " << this->age << endl;
    }
    char* getName() {
        return this->name;
    }
    int getAge() {
        return this->age;
    }
    void destroy() { //会出错,我也不知道为什么
        delete(this->name);
        delete this;
    }
};

DLL_EXPORT People* getPeople();
// DllExportTemplate.cpp 头文件实现
#include "framework.h"
#include "DllExportTemplate.h"
#include <string>
using namespace std;

DLL_EXPORT void freePointer(void* any) {
    free(any);
}
DLL_EXPORT void deletePointer(void* any) {
    delete any;
}
// 导出指针
DLL_EXPORT char* getHello(){
    char* hello = new char[] {"hello\0"};
    return hello;
}
DLL_EXPORT People* getPeople() {
    //遵守第1条
    People* p = new People(new char[] {"John"}, 100);
    return p;
}

在完成上述dll代码后,正常按照“生成解决方案”生成dll即可(推荐使用C++14标准,因为其他的我没测过,目测C++17也没问题)

二、编写addon项目

之后转到nodejs的addon项目(node-gpy项目)
项目结构如下
项目结构
把刚刚dll项目的所有头文件(如果头文件引入了别的头文件,也需要)复制到项目include下(如果复制过来报错,记得安装vscode的cpp扩展并配置好,例如cl的位置,include包含目录等,具体网上有教学)
主要代码如下:

//Main.cpp
#include "DllExportTemplate.h"
#include <iostream>
#include <napi.h>
using namespace std;

Napi::Object Initialize(Napi::Env env, Napi::Object exports){
    People* p = getPeople();
    p->showInfo();

    string name = p->getName();
    int age = p->getAge();
    char* hello = getHello();

    // 不能调用destroy,我也不知道为什么会错,必须一个一个释放
    // p->destroy();
    freePointer(p->name);
    deletePointer(p);

    exports.Set("version",Napi::String::New(env, version));
    exports.Set("hello",Napi::String::New(env, hello));
    exports.Set("name",Napi::String::New(env, name));
    exports.Set("age",Napi::Number::New(env, age));
    return exports;
}

NODE_API_MODULE(NODE_GYP_MODULE_NAME, Initialize)

随后配置好binding.gyp

{
   "targets": [{
            "target_name": "cppTemplate", //目标名称
            "cflags!": [ "-fno-exceptions" ],
            "cflags_cc!": [ "-fno-exceptions" ],
            "sources": [
                "addons/cppTemplate/Main.cpp",//这是我的路径
            ],
            "include_dirs": [
                "<!@(node -p \"require('node-addon-api').include\")",
                "addons/cppTemplate/include",//将头文件引入
            ],
            "library_dirs": [
                "addons/cppTemplate/lib" //配置lib目录
            ],
            "libraries": [
                "DllExportTemplate.lib" //将编译好的.lib文件引入编译项目
            ],
            "dependencies": [
                "<!(node -p \"require('node-addon-api').gyp\")"
            ],
            "defines": [ 'NAPI_DISABLE_CPP_EXCEPTIONS']
        }
    ]
}

之后正常通过编译即可,得到如下内容:
编译结果
主要是得到.node文件,然后将.node文件放到测试目录下,再把运行时的dll也放到根目录(相对于.node而言,如果是electron,可能是electron根目录,这个我没测过)下。为了方便测试,我直接在release目录下新建test.js做测试

const e = require("./cppTemplate.node");
console.log(e)

结果:

PS ~\build\Release> node .\test.js
John 100
{ version: '1.0.0', hello: 'hello', name: 'John', age: 100 }

可能看完会头疼,我还是总结一下流程吧:

  • 1:正常使用VS编写dll,只需要遵守上面三条规则
  • 2:编写addon项目(具体网络上有很多教程,例如如何在项目中配置node-gyp,如何配置vs,如何配置环境变量,如何配置c++环境等等等(已憋死))
  • 3:配置bingding.gyp(网上都有现成的模板,直接抄我上面的也行,记得删掉注释)
  • 4:启动node-gyp编译即可

重申:32位nodejs不能调用64位addon,反之亦然

标签:name,nodejs,void,dll,DLL,EXPORT,include,Napi
From: https://www.cnblogs.com/MCMonkey/p/18244360

相关文章

  • nodejs下载依赖npm install报错
    npminstall报错,解决记录_npmwarnusing--forcerecommendedprotectionsdis-CSDN博客先切换镜像源,然后清理缓存,在使用npm命令注意前面可能爆粗哦的原因大概率是权限问题,所以采用这种解决方式加上面合体:解决:安装vueCLI不成功时,执行npmcleancache-force清除缓存命令无效_n......
  • 微信PC版提示缺少dll文件怎么办?解决电脑微信缺失DLL文件问题的详细指南
    在使用电脑版微信时,偶尔会遇到程序启动失败或运行异常的情况,其中一种常见的错误提示是“缺少DLL文件”。DLL(DynamicLinkLibrary)文件是Windows操作系统中重要的动态链接库文件,负责存储多个程序共享的函数和数据。当电脑微信报告缺少特定DLL文件时,这意味着它无法找到执行某些功......
  • 《吸血鬼幸存者》游戏启动障碍:应对缺失DLL文件的解决方案
    如果你在尝试运行《吸血鬼幸存者》(VampireSurvivors)时遇到提示缺少特定的DLL文件问题,别急!通过重新安装、验证游戏文件、更新系统组件等简易步骤,即刻重返畅玩之旅。以下是直击问题要害的详细解决方案。1.重新安装游戏首先,确保游戏文件没有损坏或不完整,尝试卸载后重新安装......
  • Steam游戏启动受阻:有效应对bcrypt.dll文件缺失的解决方案
    面对Steam游戏启动时“bcrypt.dll文件缺失”的提示,玩家无需沮丧。通过几个简单步骤,包括验证游戏文件、安装必要运行库、系统文件检查等,即可轻松跨越这道障碍,重返游戏战场。本文速递解决方案,助你无缝继续游戏之旅。1.重新安装游戏首先,尝试从Steam库中卸载游戏,然后重新安装。......
  • CAD2023安装后遭遇acpal.dll缺失问题?快速解决方案速递
    在尝试安装或运行AutoCAD2023时,您可能会遇到提示“找不到acpal.dll”或类似错误信息,这通常意味着系统中缺少了该动态链接库文件,导致软件无法正常启动。acpal.dll是AutoCAD程序运行所必需的一个关键组件,它的缺失直接影响到软件的功能完整性。不过不用担心,以下是一套行之有效的......
  • 《火炬之光2》启动受阻?快速解决“msvcr100.dll”缺失问题!
    在满怀期待地点击《火炬之光2》的启动图标,准备沉浸于那片充满奇幻与冒险的世界时,突如其来的“msvcr100.dll缺失”错误提示无疑给玩家的热情泼了一盆冷水。别担心,这个常见问题背后有着简单的解决方案。本文将手把手教你如何迅速恢复游戏运行,让冒险之旅顺利启程。问题解析:“msv......
  • 会声会影启动报错:找不到mfc110.dll文件的全面解决策略
    在使用会声会影进行视频编辑时,遇到“丢失mfc110.dll”错误提示,无疑会给创作过程带来不小的困扰。这个错误通常意味着系统中缺少了一个重要的动态链接库文件,而mfc110.dll是MicrosoftVisualC++RedistributablePackage的一部分,对于运行许多基于VisualC++开发的应用程序至关重......
  • 使用使用rundll32 调用指定dll的方法
    使用使用rundll32调用指定dll的方法//顾名思义,"执行32位的DLL文件"。它的作用是执行DLL文件中的内部函数,这样在进程当中,只会有Rundll32.exe,而不会有DLL后门的进程,这样,就实现了进程上的隐藏。介绍一下Rundll32.exe这个文件,功能就是以命令行的方式调用动态链接程序库。系统中......
  • nw.js 如何调用activeX控件 (控件是C++编写的dll文件)
    ......
  • dnsrslvr.dll文件丢失导致程序无法运行问题
    其实很多用户玩单机游戏或者安装软件的时候就出现过这种问题,如果是新手第一时间会认为是软件或游戏出错了,其实并不是这样,其主要原因就是你电脑系统的该dll文件丢失了或没有安装一些系统软件平台所需要的动态链接库,这时你可以下载这个dnsrslvr.dll文件(挑选合适的版本文件)把它......