nodejs调用c++dll并返回结构类型

本文档展示了如何使用Node.js调用C++编写的动态链接库Fwlib32.dll,并详细解释了如何传递参数和返回结构类型数据。通过LoadLibrary和GetProcAddress函数加载库并获取函数指针,然后执行cnc_allclibhndl3、cnc_resetconnect等函数,实现与CNC设备的通信。
// cnc_resetconnect.cc
#include <node.h>
#include <node_buffer.h>


#include <iostream>
#include <windows.h>


namespace demo {


using v8::FunctionCallbackInfo;
using v8::Isolate;
using v8::Local;
using v8::Object;
using v8::String;
using v8::Value;
using v8::Number;
using v8::Uint32;
using v8::Integer;
using v8::Exception;
using v8::Array;


/* allocate library handle 3 */
//FWLIBAPI short WINAPI cnc_allclibhndl3(const char *, unsigned short, long, unsigned short *);
void Cnc_allclibhndl3(const FunctionCallbackInfo<Value>& args) {
  Isolate* isolate = args.GetIsolate();


  // Check the number of arguments passed.
  if (args.Length() != 4 ) {
    // Throw an Error that is passed back to JavaScript
    isolate->ThrowException(Exception::TypeError(
        String::NewFromUtf8(isolate, "Wrong number of arguments")));
    return;
  }


  HINSTANCE hDLL;
  hDLL=LoadLibrary("Fwlib32.dll");//加载动态链接库Fwlib32.dll文件;
  if (!hDLL) {
 // Throw an Error that is passed back to JavaScript
 DWORD dRe = GetLastError();
 char sz[4];
 sprintf(sz, "cat not get lib, error is %d", dRe);
 isolate->ThrowException(Exception::TypeError(
 String::NewFromUtf8(isolate, sz)));
 return;
  }


typedef  short(WINAPI *pMax)(const char *, unsigned short, long, unsigned short *);//函数指针
  pMax pCnc_resetconnect=NULL;
  pCnc_resetconnect=(pMax)GetProcAddress(hDLL,"cnc_allclibhndl3");
  if ( !pCnc_resetconnect ) {
    // Throw an Error that is passed back to JavaScript
    isolate->ThrowException(Exception::TypeError(
        String::NewFromUtf8(isolate, "can not get function: cnc_allclibhndl3 from Fwlib32.dll.")));
    return;
  }
 
  String::Utf8Value utf(args[0]->ToString());
  char* bufferdata = *utf;


  int a = args[1]->Uint32Value();
  int b = args[2]->Uint32Value();
  int c = args[3]->Uint32Value();


//   char buf[256];
//   sprintf(buf, "%s : %d : %d : %d", bufferdata, a, b, c);
//   MessageBox(NULL, buf, "", MB_OK);


  unsigned short iThr = c;


  short value = pCnc_resetconnect(bufferdata, a, b, &iThr);


  Local<Integer> num = Uint32::New(isolate, value);
  Local<Integer> handle = Uint32::New(isolate, iThr);


  Local<Object> obj = Object::New(isolate);
  obj->Set(String::NewFromUtf8(isolate, "re"), num);
  obj->Set(String::NewFromUtf8(isolate, "handle"), handle);

  args.GetReturnValue().Set(obj);

}


/* reset all socket connection */
//FWLIBAPI short WINAPI cnc_resetconnect(unsigned short);
void Cnc_resetconnect(const FunctionCallbackInfo<Value>& args) {
Isolate* isolate = args.GetIsolate();


// Check the number of arguments passed.
if (args.Length() != 1) {
// Throw an Error that is passed back to JavaScript
isolate->ThrowException(Exception::TypeError(
String::NewFromUtf8(isolate, "Wrong number of arguments")));
return;
}


HINSTANCE hDLL;
hDLL = LoadLibrary("Fwlib32.dll");//加载动态链接库Fwlib32.dll文件;
if (!hDLL) {
// Throw an Error that is passed back to JavaScript
DWORD dRe = GetLastError();
char sz[4];
sprintf(sz, "cat not get lib, error is %d", dRe);
isolate->ThrowException(Exception::TypeError(
String::NewFromUtf8(isolate, sz)));
return;
}


typedef  short(WINAPI *pMax)( unsigned short );//函数指针
pMax pCnc_resetconnect = NULL;
pCnc_resetconnect = (pMax)GetProcAddress(hDLL, "cnc_resetconnect");
if (!pCnc_resetconnect) {
// Throw an Error that is passed back to JavaScript
isolate->ThrowException(Exception::TypeError(
String::NewFromUtf8(isolate, "can not get function: cnc_resetconnect from Fwlib32.dll.")));
return;
}


unsigned short a = args[0]->Uint32Value();

short value = pCnc_resetconnect(a);

Local<Integer> num = Uint32::New(isolate, value);

// Set the return value (using the passed in
// FunctionCallbackInfo<Value>&)
args.GetReturnValue().Set(num);
}


#define MAX_AXIS        48
typedef struct odbaxis {
short   dummy;             /* dummy */
short   type;              /* axis number */
long    data[MAX_AXIS];    /* data value */
} ODBAXIS;


char* GetOdbaxis(short value, ODBAXIS dta, Isolate* isolate, Local<Object>& obj)
{
Local<Integer> num = Uint32::New(isolate, value);
Local<Integer> dummy = Uint32::New(isolate, dta.dummy);
Local<Integer> type = Uint32::New(isolate, dta.type);
Local<Array> arr = Array::New(isolate, MAX_AXIS );

for (int i = 0; i < MAX_AXIS; ++i)
{
arr->Set(i, Number::New(isolate, dta.data[i]) );
}

obj->Set(String::NewFromUtf8(isolate, "re"), num);
obj->Set(String::NewFromUtf8(isolate, "dummy"), dummy);
obj->Set(String::NewFromUtf8(isolate, "type"), type);
obj->Set(String::NewFromUtf8(isolate, "data"), arr);

return NULL;
}


/* read machine axis position */
//FWLIBAPI short WINAPI cnc_machine(unsigned
### 如何在 Node.js 中加载使用 C++ 编写的 DLL 文件 #### 使用 `node-ffi` 加载和调用动态链接 (DLL) 为了能够在 Node.js 应用程序中加载使用由 C++ 编写而成的 DLL 文件,可以采用名为 `node-ffi` 的工具包来完成这项工作。此工具使得利用纯 JavaScript 调用本地函数成为可能,且简化了与外部二进制接口交互的过程[^1]。 安装必要的 npm 包: ```bash npm install ffi-napi ref-napi ``` 下面是一份简单的例子,展示了怎样通过 `node-ffi` 来访问一个假设存在的 C++ 函数 `addNumbers(int, int)` 执行加法操作: ```javascript const ffi = require('ffi-napi'); const ref = require('ref-napi'); // 定义参数类型映射表以便正确传递给C++ let typesMapping = { 'int': ref.types.int, }; // 创建指向dll文件的对象实例 let myDll = new ffi.Library('./path/to/your/cpp_dll', { "addNumbers": ['int', [typesMapping['int'], typesMapping['int']]] }); console.log(myDll.addNumbers(5, 7)); // 输出应为:12 ``` 这段代码片段说明了几个要点: - 需要引入两个主要依赖项——`ffi-napi` 和 `ref-napi`;前者提供了 FFI 功能而后者帮助管理数据类型的转换。 - 当创建一个新的 Library 实例时,第一个参数是要加载的目标 dll 文件路径,第二个则是对象字面量形式的方法签名列表,其中键名对应于导出方法名称,值则表示返回值及其接受输入参数的数据类型数组。 - 对于每种预期传入或传出的数据类型,在定义这些方法之前都应当先准备好相应的映射关系。 #### 注意事项 当尝试集成现有的 C++ DLL 到基于 Node.js 构建的应用当中去时,请注意以下几点建议: - **确保 ABI 兼容性**:确认所使用的平台架构(比如 Windows 上 x86 或者 x64)与目标 DLL 是一致的,因为不同体系结构下的应用程序二进制接口可能会有所差异[^3]。 - **理解内存管理和生命周期**:由于涉及到两种不同的编程环境之间的互操作,因此对于资源分配、释放以及异常处理等方面要有清晰的认识,防止潜在的风险如内存泄漏等问题的发生。 - **掌握基本的 C/C++ 知识**:尽管可以直接从 JS 层面上发起对原生 API 的请求,但对于那些底层细节的理解仍然是不可或缺的一部分,特别是在调试阶段更是如此。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值