- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
设置:
我有一个 NODE.JS 应用程序,必须以低延迟执行一些计算
我决定使用 N-API 和 node-gyp 将 native C++ 模块包含到 NODE.JS 应用程序
当前状态:
我已经到了工具链工作的地步,我可以将 C++ 源代码编译成二进制文件,将二进制模块包含在 NODE.JS 应用程序中,NODE.JS 应用程序执行
我可以从 NODE.JS 调用具有标准 NODE.JS 类型的 C++ 方法,并且这些方法在执行完成后可以将标准 NODE.JS 类型返回到 NODE.JS
问题:
我不知道如何将自定义类型/对象从 C++ 返回到 NODE.JS
目前我想基本上返回一个具有多种类型的结构,以便在单个 NODE.JS 调用中将复杂解析的结果返回给 NODE.JS
最小代码输出:
我做了一个最小的实现来展示我想做的事情。如果您注释#define ENABLE_RETURN_CLASS
,则代码仅使用标准 NODE.JS 类型,并且一切正常。下面是输出图像,显示了工具链和执行情况:
如果您离开#define ENABLE_RETURN_CLASS
,代码将无法编译。据我所知,它不理解如何从 C++ 对象转换为 NODE.JS 对象。这是错误:
最少代码:
初始化 NODE.JS 应用程序
npm init
npm install node-gyp --save-dev
npm install node-addon-api
将 C++ 二进制文件编译为 NODE.JS 模块
npm run build
启动 NODE.JS 应用程序
node main.js
代码可以在此存储库中找到:
https://github.com/OrsoEric/2020-01-18-Test-NODEJS-Return-Class
我计划在找到解决方案后进行更新。
我想要返回到 NODE.JS 应用程序的类的代码:
my_class.h
namespace User
{
//Class I want to return to NODE.JS
class My_class
{
public:
//Constructor
My_class( void );
//Public references
float &my_float( void );
int &my_int( void );
private:
//Private class vars
float g_my_float;
int g_my_int;
};
} //End namestace: User
my_class.cpp
#include <iostream>
//Class header
#include "my_class.h"
namespace User
{
//Constructor
My_class::My_class( void )
{
this -> g_my_float = (float)1.001;
this -> g_my_int = (int)42;
}
//Public Reference
float &My_class::my_float( void )
{
return this -> g_my_float;
}
//Public Reference
int &My_class::my_int( void )
{
return this -> g_my_int;
}
} //End namestace: User
C++ 和 NODE.JS 之间的绑定(bind)代码。 #define ENABLE_RETURN_CLASS
启用返回类的代码。本例中的实例是一个全局变量。
node_bindings.cpp
//NODE bindings
#include <napi.h>
//C++ Class I want to return to NODE.JS
#include "my_class.h"
//Comment to disable the code that return the class instance
//#define ENABLE_RETURN_CLASS
//Instance of My_class I want to return to NODE.JS
User::My_class g_instance;
//Prototype of function called by NODE.JS that initializes this module
extern Napi::Object init(Napi::Env env, Napi::Object exports);
//Prototype of function that returns a standard type: WORKS
extern Napi::Number get_my_float(const Napi::CallbackInfo& info);
#ifdef ENABLE_RETURN_CLASS
//Prototype of function that returns My_class to NODE.JS: DOES NOT WORK!!!
extern Napi::Object get_my_class(const Napi::CallbackInfo& info);
#endif // ENABLE_RETURN_CLASS
//Initialize instance
Napi::Object init(Napi::Env env, Napi::Object exports)
{
//Construct the instance of My_class I want to return to NODE.JS
g_instance = User::My_class();
//Register methods accessible from the outside in the NODE.JS environment
//Return a standard type
exports.Set( "get_my_float", Napi::Function::New(env, get_my_float) );
#ifdef ENABLE_RETURN_CLASS
//Return the whole class
exports.Set( "get_my_class", Napi::Function::New(env, get_my_class) );
#endif
return exports;
} //End function: init | Napi::Env | Napi::Object
//Interface between function and NODE.JS
Napi::Number get_my_float(const Napi::CallbackInfo& info)
{
Napi::Env env = info.Env();
//Check arguments
if (info.Length() != 0)
{
Napi::TypeError::New(env, "ERR: Expecting no arguments").ThrowAsJavaScriptException();
}
//Get the return value
float tmp = g_instance.my_float();
//Return a NODE.JS number
return Napi::Number::New(env, (float)tmp);
} //End Function: get_my_float | Napi::CallbackInfo&
#ifdef ENABLE_RETURN_CLASS
//Interface between function and NODE.JS
Napi::Object get_my_class(const Napi::CallbackInfo& info)
{
Napi::Env env = info.Env();
//Check arguments
if (info.Length() != 0)
{
Napi::TypeError::New(env, "ERR: Expecting no arguments").ThrowAsJavaScriptException();
}
//Get the return value
User::My_class tmp = g_instance;
//Return a NODE.JS number
return Napi::Object::New(env, (User::My_class)tmp);
} //End Function: get_my_float | Napi::CallbackInfo&
#endif // ENABLE_RETURN_CLASS
NODE_API_MODULE( My_cpp_module, init )
NODE.JS 应用程序 main.js 包含并执行 C++ 模块:
//Include native C++ module
const my_custom_cpp_module = require('./build/Release/MyCustomCppModule.node');
console.log('My custom c++ module',my_custom_cpp_module);
//TEST:
tmp = my_custom_cpp_module.get_my_float();
console.log( tmp );
module.exports = my_custom_cpp_module;
绑定(bind)在文件 binding.gyp 中进行了描述:
{
"targets": [{
"target_name": "MyCustomCppModule",
"cflags!": [ "-fno-exceptions" ],
"cflags_cc!": [ "-fno-exceptions" ],
"sources": [
"node_bindings.cpp",
"my_class.cpp"
],
'include_dirs': [
"<!@(node -p \"require('node-addon-api').include\")"
],
'libraries': [],
'dependencies': [
"<!(node -p \"require('node-addon-api').gyp\")"
],
'defines': [ 'NAPI_DISABLE_CPP_EXCEPTIONS' ]
}]
}
而 package.json 是 NODE.JS 需要解析依赖项、编译和运行的
{
"name": "2020-01-18-test-return-object",
"version": "1.0.0",
"description": "",
"main": "main.js",
"scripts": {
"build": "node-gyp rebuild",
"clean": "node-gyp clean"
},
"author": "",
"license": "ISC",
"gypfile": true,
"devDependencies": {
"node-gyp": "^6.1.0"
},
"dependencies": {
"node-addon-api": "^2.0.0"
}
}
<小时/>
我无法在 Napi::Object 中安装自定义类,但我可以创建一个空的 Napi::Object 并一一创建字段。 https://github.com/OrsoEric/2020-01-18-Test-NODEJS-Return-Class
在 node_bindings.cpp
//NODE bindings
#include <napi.h>
//C++ Class I want to return to NODE.JS
#include "my_class.h"
//Comment to disable the code that return the class instance
#define ENABLE_RETURN_CLASS
//Instance of My_class I want to return to NODE.JS
User::My_class g_instance;
//Prototype of function called by NODE.JS that initializes this module
extern Napi::Object init(Napi::Env env, Napi::Object exports);
//Prototype of function that returns a standard type: WORKS
extern Napi::Number get_my_float(const Napi::CallbackInfo& info);
#ifdef ENABLE_RETURN_CLASS
//Prototype of function that returns My_class to NODE.JS: DOES NOT WORK!!!
extern Napi::Object get_my_class(const Napi::CallbackInfo& info);
#endif // ENABLE_RETURN_CLASS
//Initialize instance
Napi::Object init(Napi::Env env, Napi::Object exports)
{
//Construct the instance of My_class I want to return to NODE.JS
g_instance = User::My_class();
//Register methods accessible from the outside in the NODE.JS environment
//Return a standard type
exports.Set( "get_my_float", Napi::Function::New(env, get_my_float) );
#ifdef ENABLE_RETURN_CLASS
//Return the whole class
exports.Set( "get_my_class", Napi::Function::New(env, get_my_class) );
#endif
return exports;
} //End function: init | Napi::Env | Napi::Object
//Interface between function and NODE.JS
Napi::Number get_my_float(const Napi::CallbackInfo& info)
{
Napi::Env env = info.Env();
//Check arguments
if (info.Length() != 0)
{
Napi::TypeError::New(env, "ERR: Expecting no arguments").ThrowAsJavaScriptException();
}
//Get the return value
float tmp = g_instance.my_float();
//Return a NODE.JS number
return Napi::Number::New(env, (float)tmp);
} //End Function: get_my_float | Napi::CallbackInfo&
#ifdef ENABLE_RETURN_CLASS
//Interface between function and NODE.JS
Napi::Object get_my_class(const Napi::CallbackInfo& info)
{
Napi::Env env = info.Env();
//Check arguments
if (info.Length() != 0)
{
Napi::TypeError::New(env, "ERR: Expecting no arguments").ThrowAsJavaScriptException();
}
//Get a copy of the instance of the class I want to return
User::My_class tmp = g_instance;
//Construct empty return object in the NODE.JS environment
Napi::Object ret_tmp = Napi::Object::New( env );
//Manually create and fill the fields of the return object
ret_tmp.Set("my_float", Napi::Number::New( env, (float)tmp.my_float() ));
ret_tmp.Set("my_int", Napi::Number::New( env, (int)tmp.my_int() ));
//Return a NODE.JS Object
return (Napi::Object)ret_tmp;
} //End Function: get_my_class | Napi::CallbackInfo&
#endif // ENABLE_RETURN_CLASS
NODE_API_MODULE( My_cpp_module, init )
在main.js中添加测试指令:
//Include native C++ module
const my_custom_cpp_module = require('./build/Release/MyCustomCppModule.node');
console.log('My custom c++ module',my_custom_cpp_module);
//TEST: Standard NODE.JS type
tmp = my_custom_cpp_module.get_my_float();
console.log( tmp );
//Custom NODE.JS type
class_tmp = my_custom_cpp_module.get_my_class();
console.log( class_tmp );
module.exports = my_custom_cpp_module;
最佳答案
我认为,如 Napi::Object docs 中所述,您不能使用自定义类实例化对象。只有原始值。因此,我建议创建一个空的 Napi::Object
并使用其 Set
来映射值。
Napi::Object ret = Napi::Object::New(env);
ret.Set("my_float", Napi::Number::New(env, (float)tmp.my_float()));
填写所有字段并返回对象。就像您对 exports
关于c++ - 如何将 C++ 类返回到 NODE.JS,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59799509/
#include using namespace std; class C{ private: int value; public: C(){ value = 0;
这个问题已经有答案了: What is the difference between char a[] = ?string?; and char *p = ?string?;? (8 个回答) 已关闭
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 7 年前。 此帖子已于 8 个月
除了调试之外,是否有任何针对 c、c++ 或 c# 的测试工具,其工作原理类似于将独立函数复制粘贴到某个文本框,然后在其他文本框中输入参数? 最佳答案 也许您会考虑单元测试。我推荐你谷歌测试和谷歌模拟
我想在第二台显示器中移动一个窗口 (HWND)。问题是我尝试了很多方法,例如将分辨率加倍或输入负值,但它永远无法将窗口放在我的第二台显示器上。 关于如何在 C/C++/c# 中执行此操作的任何线索 最
我正在寻找 C/C++/C## 中不同类型 DES 的现有实现。我的运行平台是Windows XP/Vista/7。 我正在尝试编写一个 C# 程序,它将使用 DES 算法进行加密和解密。我需要一些实
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
有没有办法强制将另一个 窗口置于顶部? 不是应用程序的窗口,而是另一个已经在系统上运行的窗口。 (Windows, C/C++/C#) 最佳答案 SetWindowPos(that_window_ha
假设您可以在 C/C++ 或 Csharp 之间做出选择,并且您打算在 Windows 和 Linux 服务器上运行同一服务器的多个实例,那么构建套接字服务器应用程序的最明智选择是什么? 最佳答案 如
你们能告诉我它们之间的区别吗? 顺便问一下,有什么叫C++库或C库的吗? 最佳答案 C++ 标准库 和 C 标准库 是 C++ 和 C 标准定义的库,提供给 C++ 和 C 程序使用。那是那些词的共同
下面的测试代码,我将输出信息放在注释中。我使用的是 gcc 4.8.5 和 Centos 7.2。 #include #include class C { public:
很难说出这里问的是什么。这个问题是含糊的、模糊的、不完整的、过于宽泛的或修辞性的,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开它,visit the help center 。 已关
我的客户将使用名为 annoucement 的结构/类与客户通信。我想我会用 C++ 编写服务器。会有很多不同的类继承annoucement。我的问题是通过网络将这些类发送给客户端 我想也许我应该使用
我在 C# 中有以下函数: public Matrix ConcatDescriptors(IList> descriptors) { int cols = descriptors[0].Co
我有一个项目要编写一个函数来对某些数据执行某些操作。我可以用 C/C++ 编写代码,但我不想与雇主共享该函数的代码。相反,我只想让他有权在他自己的代码中调用该函数。是否可以?我想到了这两种方法 - 在
我使用的是编写糟糕的第 3 方 (C/C++) Api。我从托管代码(C++/CLI)中使用它。有时会出现“访问冲突错误”。这使整个应用程序崩溃。我知道我无法处理这些错误[如果指针访问非法内存位置等,
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 7 年前。
已关闭。此问题不符合Stack Overflow guidelines 。目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是偏离主题的,因为
我有一些 C 代码,将使用 P/Invoke 从 C# 调用。我正在尝试为这个 C 函数定义一个 C# 等效项。 SomeData* DoSomething(); struct SomeData {
这个问题已经有答案了: Why are these constructs using pre and post-increment undefined behavior? (14 个回答) 已关闭 6
我是一名优秀的程序员,十分优秀!