C++ 从 Node 模拟 int main(int argc, char *argv[])

标签 c++ arrays node.js node-gyp

基本上,我正在使用 NAPI 功能将现有的 C++ 文件与我们的 javascript/Node 集成。我让它在一个测试 C++ 文件上工作,所以我知道我的设置工作正常。然而,在实际的 C++ 文件中,它被设计为使用命令行中的 argc 和 argv 从命令行运行。基本上我只需要从我的其他函数内部调用 C++ 中的 main 方法,这意味着没有命令行。所以我必须传入 argc 和 argv 的值。 argc 只是一个 int,这很简单,但是 argc 是一个 char ** 类型,根据我的研究,它看起来像是一个字符数组的数组,又名字符串?

这是我当前的代码,位于我的 C++ 文件底部

void Init(Env env, Object exports, Object module) {
    exports.Set("main", Function::New(env, main(2,{"test","test2"})));
}
NODE_API_MODULE(addon, Init)

argc 值工作正常

我正在尝试创建一个临时/测试值以供 argv 传入,但我在弄清楚如何使用我的值创建 char ** 类型的数组时遇到问题。

最佳答案

argv是一个指向字符串的指针数组(实际上是以 NUL 结尾的字符数组),其中元素 0 是程序的名称,元素 1 ... argc-1是程序参数,元素 argc必须是NULL 1

C++ 中没有数组文字,因此您必须显式创建数组变量以将其传递给函数。更糟糕的是,main允许修改传递的参数,因此您甚至无法构建字符串文字数组,因为它们是只读的;因此,您必须为每个参数显式分配读/写空间。一个准系统的解决方案可以是为每个参数使用单个缓冲区并从中构建指针数组:

char argv0[] = "test_program";
char argv1[] = "arg1";
char argv2[] = "arg2";
char *argv[] = {argv0, argv1, argv2, NULL};
main(3, argv);

一种更灵活的方法(特别是当您必须动态构建参数时)可以是使用 std::vector<std::string> :

std::vector<std::string> args = { "test_program", "arg1", "arg2" };
// ... here you may add other arguments dynamically...
args.push_back("arg3"); // whatever
// build the pointers array
std::vector<char *> argv;
for(std::string &s: args) argv.push_back(&s[0]);
argv.push_back(NULL);
main(argv.size()-1, argv.data());

现在,来看您的代码:

void Init(Env env, Object exports, Object module) {
    exports.Set("main", Function::New(env, main(2,{"test","test2"})));
}
NODE_API_MODULE(addon, Init)

除了您无法构建 argv 的事实之外传递至main像这样,您正在尝试调用 main并将其结果作为第二个参数传递给 Function::New ,而Function::New wants some callable type (例如函数指针)注册为名为 main 的导出的处理程序!复制自 Function::New文档:

/// Callable must implement operator() accepting a const CallbackInfo&
/// and return either void or Value.

因此,作为一个简单的示例,您可以通过注册如下回调将 main 导出为无参数 JS 函数,该函数不返回任何内容( undefined ,我猜?):

void MainCallback(const CallbackInfo& info) {
    char argv0[] = "test_program";
    char argv1[] = "arg1";
    char argv2[] = "arg2";
    char *argv[] = {argv0, argv1, argv2, NULL};
    main(3, argv);
}

void Init(Env env, Object exports, Object module) {
    exports.Set("main", Function::New(env, MainCallback));
}
NODE_API_MODULE(addon, Init)

最后,正如其他人所说,技术上是用 C++ main有点神奇——从程序内部调用它是未定义的行为;实际上,在我知道的任何平台上也可以运行node.js,main是一个完全常规的函数,恰好由 C 运行时在启动时调用,因此我认为这不会给您带来任何问题。


注释

  1. 因此,您可以说它是一个以 NUL 结尾的字符数组的 NULL 结尾数组。请注意这里NULL = 空指针; NUL = 字符串终止符,即'\0' .

关于C++ 从 Node 模拟 int main(int argc, char *argv[]),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46186052/

相关文章:

javascript - 导入/更改 HTML 内容(ES6 更新后)

javascript - Passport.js req.user 返回 : 'Promise { false }' - How do I get the current sessions' username?

javascript - 我应该担心清理 Node.js 中的大对象还是留给垃圾收集器?

c++ - glTexImage*D 参数冗余?

c++ - 如何在另一个#define 中实现#define?

javascript - 为什么 JavaScript 将名为 "name"的数组解析为字符串

javascript - loadData() 返回空数组

c++ - 定义清晰但角度变化的图像的图像识别

c++ - 检查 CRL OpenSSL C

java - 从文件流式传输 n 个整数列表以创建 n 个对象数组