You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在C++项目中实现向NodeJS传递Buffer并处理后回传?

实现C++向NodeJS传递Buffer并接收处理后结果的方案

需求说明

需要在C项目中集成Node.js,实现**C主动将Buffer传递给Node.js处理,再接收Node.js返回的处理后Buffer**的流程。此前基于NAN模块仅实现了Node.js向C++传递Buffer并处理后回传的反向流程,不符合需求。

现有代码

buffer_example.cpp

NAN_METHOD(rotate)
{
    char* buffer = static_cast<char*>(node::Buffer::Data(info[0].As<Object>()));
    v8::Local<v8::Context> context = v8::Context::New(v8::Isolate::GetCurrent());
    uint32_t size;
    uint32_t rot;
    
    if(info[1]->IsUint32())
    {
        size = info[1]->ToUint32(context).ToLocalChecked()->Value();
    }

    if(info[2]->IsUint32())
    {
        rot = info[2]->ToUint32(context).ToLocalChecked()->Value();
    }
    
   
    for(uint32_t i = 0; i < size; i++ )
    {
        buffer[i] += rot;
    }
}

NAN_MODULE_INIT(Init)
{
    Nan::Set(target, New<String>("rotate").ToLocalChecked(),
        GetFunction(New<FunctionTemplate>(rotate)).ToLocalChecked());
}

NODE_MODULE(NODE_GYP_MODULE_NAME, Init)

index.js

'use strict';
// Requiring the add-on that we'll build in a moment...
const addon = require('./build/Release/buffer_example');

// Allocates memory holding ASCII "ABC" outside of V8.
const buffer = Buffer.from("ABC");
// synchronous, rotates each character by +13
addon.rotate(buffer, buffer.length, 13);

解决方案

是否需要分开插件?

不需要,单个NAN插件即可实现双向交互逻辑,核心是在C++中调用Node.js的处理函数,并接收其返回结果。

具体实现步骤

  1. Node.js端:编写处理Buffer的函数,接收输入Buffer,处理后返回新的Buffer或修改原Buffer(根据需求选择)。
  2. C++端:
    • 加载Node.js模块并获取处理函数的引用;
    • 将C++中的内存封装为Node.js Buffer对象;
    • 调用Node.js处理函数并传递Buffer;
    • 解析Node.js返回的Buffer,提取数据到C++内存中。

修改后的代码示例

1. Node.js端(index.js)

新增处理函数,示例为对Buffer内容做ROT13处理后返回:

'use strict';
const addon = require('./build/Release/buffer_example');

// 定义Node.js侧的Buffer处理函数
function processBuffer(inputBuffer) {
    const processed = Buffer.alloc(inputBuffer.length);
    for (let i = 0; i < inputBuffer.length; i++) {
        let charCode = inputBuffer[i];
        if ((charCode >= 65 && charCode <= 90) || (charCode >= 97 && charCode <= 122)) {
            const base = charCode >= 97 ? 97 : 65;
            processed[i] = ((charCode - base + 13) % 26) + base;
        } else {
            processed[i] = charCode;
        }
    }
    return processed;
}

// 将处理函数暴露给C++
global.processBuffer = processBuffer;

// 保留原有反向逻辑(可选)
const buffer = Buffer.from("ABC");
addon.rotate(buffer, buffer.length, 13);

// 触发C++调用Node.js处理函数
addon.callNodeProcessBuffer();

2. C++端(buffer_example.cpp)

新增C++调用Node.js函数并接收返回值的逻辑:

#include <nan.h>
#include <node.h>
#include <cstdio>
#include <cstring>

// 原有rotate函数(保留反向逻辑,可选)
NAN_METHOD(rotate)
{
    char* buffer = static_cast<char*>(node::Buffer::Data(info[0].As<Object>()));
    v8::Local<v8::Context> context = v8::Isolate::GetCurrent()->GetCurrentContext();
    uint32_t size = 0;
    uint32_t rot = 0;
    
    if(info[1]->IsUint32())
    {
        size = info[1]->ToUint32(context).ToLocalChecked()->Value();
    }

    if(info[2]->IsUint32())
    {
        rot = info[2]->ToUint32(context).ToLocalChecked()->Value();
    }
    
    for(uint32_t i = 0; i < size; i++ )
    {
        buffer[i] += rot;
    }
}

// 新增:C++调用Node.js的processBuffer函数并接收结果
NAN_METHOD(callNodeProcessBuffer)
{
    v8::Isolate* isolate = v8::Isolate::GetCurrent();
    v8::Local<v8::Context> context = isolate->GetCurrentContext();

    // 1. 获取全局对象中的processBuffer函数
    v8::Local<v8::Value> processBufferVal = context->Global()->Get(context, Nan::New("processBuffer").ToLocalChecked()).ToLocalChecked();
    if (!processBufferVal->IsFunction()) {
        Nan::ThrowError("processBuffer function not found in global scope");
        return;
    }
    v8::Local<v8::Function> processBufferFunc = processBufferVal.As<v8::Function>();

    // 2. C++侧构造输入数据并封装为Node.js Buffer
    const char* inputData = "ABC";
    size_t inputSize = strlen(inputData);
    v8::Local<v8::Object> inputBuffer = Nan::CopyBuffer(inputData, inputSize).ToLocalChecked();

    // 3. 调用Node.js处理函数
    v8::Local<v8::Value> args[] = { inputBuffer };
    v8::Local<v8::Value> result = processBufferFunc->Call(context, context->Global(), 1, args).ToLocalChecked();

    // 4. 解析返回的Buffer并提取到C++内存
    if (!result->IsObject() || !node::Buffer::HasInstance(result.As<v8::Object>())) {
        Nan::ThrowError("Node.js function did not return a Buffer");
        return;
    }
    char* outputData = static_cast<char*>(node::Buffer::Data(result.As<v8::Object>()));
    size_t outputSize = node::Buffer::Length(result.As<v8::Object>());

    // 示例:打印处理后的数据(C++侧可自行复用该数据)
    printf("Processed buffer from Node.js: %.*s\n", static_cast<int>(outputSize), outputData);
}

NAN_MODULE_INIT(Init)
{
    // 注册原有rotate函数
    Nan::Set(target, Nan::New<String>("rotate").ToLocalChecked(),
        Nan::GetFunction(Nan::New<v8::FunctionTemplate>(rotate)).ToLocalChecked());
    
    // 注册新增的调用函数
    Nan::Set(target, Nan::New<String>("callNodeProcessBuffer").ToLocalChecked(),
        Nan::GetFunction(Nan::New<v8::FunctionTemplate>(callNodeProcessBuffer)).ToLocalChecked());
}

NODE_MODULE(NODE_GYP_MODULE_NAME, Init)

关键说明

  • 内存管理:使用Nan::CopyBuffer会创建内存副本,若需共享C++侧内存,可改用Nan::NewBuffer,但需自行管理内存释放,避免内存泄漏。
  • 异步优化:示例为同步调用,若处理耗时操作,建议用NAN异步工作器实现异步调用,避免阻塞C++主线程。

内容的提问来源于stack exchange,提问作者Thiago Cavalcante

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 17:10:14