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

时间:2017-09-12 22:11:31

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

基本上我正在使用他们的NAPI功能将现有的C ++文件与我们的javascript /节点集成。我有一个测试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 **类型的数组。

1 个答案:

答案 0 :(得分:2)

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. 所以,你可以说它是一个以NULL结尾的NUL终止字符数组的数组。请注意,这里NULL =空指针; NUL =字符串终止符,即'\0'