NodeJs & C++ 插件 获取内存十六进制表示

595 阅读1分钟

最近看到一个前端问题,如何用十六进制写出双精度浮点数 13.25 在计算机内存中的表示

例:双精度浮点数 3.5 在内存中表示为 00 00 00 00 00 00 0c 40 (左边为内存低地址,右边为高地址)

需求升级

如果抽象为一个函数,传入任何一个 number,返回对应内存的字符串表示

function get_double_mem (x: number): string {}

首先 C++ 怎么打印内存信息

以下是一段打印内存信息,并以十六进制显示的示例代码

#include <iostream>
using namespace std;

void memory_dump(void *ptr, int len) {
    int i;
    printf("%p\n", ptr);
    for (i = 0; i < len; i++) {
        if (i % 8 == 0 && i != 0)
            printf(" ");
        if (i % 16 == 0 && i != 0)
            printf("\n");
        int mem = *((uint8_t *)ptr + i);
        printf("%02x ", mem);
    }
    printf("\n");
}

  
int main ()
{
  double yams0 = 3.5; // 00 00 00 00 00 00 0c 40
  double yams1 = 13.25; // 00 00 00 00 00 80 2a 40
  memory_dump(&yams1, sizeof(yams1));
  return 0;
}

NodeJs & C++ 插件

插件是用 C++ 编写的动态链接共享对象,用 require()函数可以将插件加载为普通的 NodeJs 模块,插件提供 JavaScript 和 C/C++ 库之间的接口。 如何编写一个C++语言的插件,暴露例如: 内存检查方法,提供NodeJs使用那,以下是一段插件代码示例

#include <iostream>
// 需要node.h头文件
#include <node.h>

namespace demo { 
  using v8::Exception;
  using v8::FunctionCallbackInfo;
  using v8::Isolate;
  using v8::Local;
  using v8::Number;
  using v8::Object;
  using v8::String;
  using v8::Value;

  // 获取内存的方法
  void MemoryDump(const FunctionCallbackInfo<Value>& args) {
    Isolate* isolate = args.GetIsolate();
    // 如果参数大于一个 error
    if (args.Length() > 1) {
      isolate->ThrowException(
        Exception::TypeError(
          String::NewFromUtf8(
            isolate,
            "Wrong number of arguments"
          ).ToLocalChecked()
        )
      );
      return;
    }
    // 如果参数不是一个数值 error
    if (!args[0]->IsNumber()) {
      isolate->ThrowException(
        Exception::TypeError(
          String::NewFromUtf8(
            isolate,
            "Wrong arguments type"
          ).ToLocalChecked()
        )
      );
      return;
    }
    // 打印该变量在内存中的地址 例如:0x30607a260
    printf("%p\n", args[0]);
    int mem;
    for (int i = 0; i < len; i++) {
        if (i % 8 == 0 && i != 0)
            printf(" ");
        if (i % 16 == 0 && i != 0)
            printf("\n");
        mem = *((uint8_t *)args[0] + i);    
        printf("%02x ", mem);
    }
    printf("\n");
    // 设置返回值
    args.GetReturnValue().Set(mem);
  }

  void Initialize(Local<Object> export) {
    NODE_SET_METHOD(exports, "get_double_mem", MemoryDump)
  }
  
  NODE_MODULE(NODE_GYP_MODULE_NAME, Initialize);
}

所有 NodeJs 插件都必须按照以下模式导出初始化函数:

void Initialize(Local<Object> exports);
NODE_MODULE(NODE_GYP_MODULE_NAME, Initialize)

node-gyp

安装 node-gyp npm install -g node-gyp, 调用 node-gyp build 命令生成编译addon.node 文件, 放入build/Release/目录中, 构建后,可以通过 require() 在 NodeJs中使用二进制插件

// test.js
const addon = require('./build/Release/addon');

console.log('00 00 00 00 00 80 2a 40:', addon.get_double_mem(13.25));