有一个简单的c++类,使用fstream
来写/读二进制文件Controller.h
:
#pragma once
#include <iostream>
#include <fstream>
#include <cstring>
#include <string>
#include <stdio.h>
using namespace std;
template <typename T>
class Controller
{
private:
T buf;
char name[40]{};
public:
explicit Controller(char *name) { strcpy(this->name, name); }
char *GetName() { return name; }
bool Insert(T model);
// int Search(T &bus);
// int Delete(T model);
};
template <typename T>
bool Controller<T>::Insert(T model)
{
fstream file;
string db_dir = "data//";
string file_path = db_dir + name;
file.open(file_path.c_str(), ios::out | ios::binary);
if (file.fail() || file.bad())
{
cout << "Failed" << endl;
return false;
}
file.write((char *)&model, sizeof(model));
file.close();
cout << "Successfully wrote" << endl;
return true;
}
上面用gcc
编译的代码工作正常。Insert
函数在db//file.dat
中创建一个二进制文件。但是如何使用Node -gyp实现与Node插件相同的功能?
我的binding.gyp
:
{
"targets": [{
"target_name": "TDS",
"cflags!": ["-fno-exceptions"],
"cflags_cc!": ["-fno-exceptions"],
"sources": [
"modules/src/main.cpp"
],
"include_dirs": [
# "node_modules/node-addon-api",
"<!(node -e "require('nan')")",
"<!(node -p "require('node-addon-api').include_dir")"
],
'libraries': [],
'dependencies': [
"<!(node -p "require('node-addon-api').gyp")"
],
'defines': ['NAPI_DISABLE_CPP_EXCEPTIONS']
}]
}
和我的modules/src/main.cpp
:
#include <napi.h>
#include "controller/Controller.h"
#include "auth/Login.cpp"
#include "model/Structs.h"
using namespace Napi;
using namespace std;
Value InsertProducto(const CallbackInfo &info)
{
Env env = info.Env();
if (!info[0].IsObject())
{
TypeError::New(env, "Wrong arguments").ThrowAsJavaScriptException();
return env.Null();
}
Object obj = info[0].ToObject();
Array props = obj.GetPropertyNames();
// for (unsigned int j = 0; j < props.Length(); j++)
// {
// // printf("key: %s: value: %sn",
// // props.Get(j).ToString().Utf8Value().c_str(),
// // obj.Get(props.Get(j)).ToString().Utf8Value().c_str());
// string key = props.Get(j).ToString().Utf8Value();
// cout << obj.Get(key).ToString().Utf8Value().c_str() << endl;
// }
Producto producto = *new Producto();
producto.id = obj.Get("id").ToNumber().Int32Value();
producto.id_proveedor = obj.Get("id_proveedor").ToNumber().Int32Value();
producto.stock = obj.Get("stock").ToNumber().Int64Value();
producto.precio = obj.Get("precio").ToNumber().FloatValue();
string descripcion = obj.Get("descripcion").ToString().Utf8Value();
if (descripcion.length() > sizeof(producto.descripcion))
{
string mssg = "Excedeed maximum size: " +
sizeof(producto.descripcion);
cout << mssg << endl;
TypeError::New(env, mssg).ThrowAsJavaScriptException();
return env.Null();
}
strcpy(producto.descripcion, descripcion.c_str());
producto.stock_min = obj.Get("stock_min").ToNumber().Int64Value();
cout << "Producto id: " << producto.id << endl;
cout << "Producto id_proveedor: " << producto.id_proveedor << endl;
cout << "Producto stock: " << producto.stock << endl;
cout << "Producto precio: " << producto.precio << endl;
cout << "Producto descripcion: " << producto.descripcion << endl;
cout << "Producto stock_min: " << producto.stock_min << endl;
Controller<Producto> controller((char *)"Cliente.dat");
if (!controller.Insert(producto))
{
return String::New(env, "Failed");
}
return String::New(env, "Successfully inserted");
}
Object Init(Env env, Object exports)
{
exports.Set(String::New(env, "InsertProducto"), Function::New<InsertProducto>(env));
return exports;
}
// Register and initialize native add-on
NODE_API_MODULE(NODE_GYP_MODULE_NAME, Init);
我可以这样在JavaScript中使用这个函数:
var TDS = require('../build/Release/TDS.node');
const producto = {
"id": "1",
"id_proveedor": "1",
"stock": "5",
"precio": "50.0",
"descripcion": "Un producto",
"stock_min": "500"
}
console.log(TDS);
console.log(TDS.InsertProducto(producto));
module.exports = TDS;
和一切工作,除了controller.Insert
调用使用相同的Controller.h
从上面。我总是看到"Failed"
的消息。
如何写/读任何二进制文件使用c++节点插件?
这里是源代码给任何人想给它一个尝试:https://github.com/JesusJimenezG/transactional-system-managemente
通过改变访问文件夹的方式来解决这个问题:
代替:
string db_dir = "data/";
string file_path = db_dir + name;
我现在使用filesystem::current_path()
:
filesystem::path cwd = std::filesystem::current_path() / name;
file.open(cwd.c_str(), ios::out | ios::binary);
这个方法有效!