This question already has answers here:
Defining own main functions arguments argc and argv
(6 answers)
Closed 6 years ago.
Hi very newbie question but I just can't figure it out:
I have a function named bar
class foo
{
public:
bool bar(int argc, char** argv);
}
argv is supposed to contain
"--dir" and "/some_path/"
How do I create argv and argc so that I can pass them into bar() ? I've tried many ways but I just can't get pointer and type conversion right.
So instead of getting argv from command line, I want to create it in the code.
Thank you for any input!
My favourite way is like this:
std::vector<std::string> arguments = {"--dir", "/some_path"};
std::vector<char*> argv;
for (const auto& arg : arguments)
argv.push_back((char*)arg.data());
argv.push_back(nullptr);
f.bar(argv.size() - 1, argv.data());
Note, that if arguments are static and do not change, then this is a little bit overkill. But this approach has advantage of being RAII compliant. It manages memory for you and deletes objects at right moment. So if argument list is dynamic, then it is the cleanest way.
Beside that, this code technically is UB if f.bar modifies data in argv array. Usually this is not the case.
Assuming you want argc and argv in the same format that are passed to main, you can call it like this:
foo f;
char *args[] = {
(char*)"--dir",
(char*)"/some_path/",
NULL
};
f.bar(2, args);
(note: this assumes bar won't modify the argument strings - in which case you should change the argument type to const char ** instead of char **)
Related
Basically I am working on integrating an existing C++ file with our javascript / node using their NAPI, functionality. I have it working on a test C++ file so I know I have the setup working. However on the actual C++ file it is designed to run from the command line with argc and argv from the command line. Basically I just need to invoke the main method in C++ from inside of my other function, which means there is no command line. So I have to pass in values for argc and argv. argc is just an int, that is easy enough, but argc is a char ** type, which from my research looks like it is an array of character arrays aka strings?
This is my current code at the bottom of my c++ file
void Init(Env env, Object exports, Object module) {
exports.Set("main", Function::New(env, main(2,{"test","test2"})));
}
NODE_API_MODULE(addon, Init)
The argc value is working fine
I am trying to create a temporary / test value for argv to pass in but I am having an issue figuring out how to make an array of type char ** with my values.
argv is an array of pointers to strings (actually, NUL-terminated character arrays), where element 0 is the name of the program, elements 1 ... argc-1 are the program arguments, and element argc must be NULL1.
There's no array literal in C++, so you have to create explicitly an array variable to pass it to a function. Even worse, main is allowed to modify the passed arguments, so you cannot even build an array of string literals, as they are read only; thus, you have to explicitly allocate read/write space for each argument. A barebones solution can be to have single buffers for each argument and build the pointer array out of them:
char argv0[] = "test_program";
char argv1[] = "arg1";
char argv2[] = "arg2";
char *argv[] = {argv0, argv1, argv2, NULL};
main(3, argv);
A more flexible one (especially if you have to build your arguments dynamically) can be to use an 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());
Now, coming to your code:
void Init(Env env, Object exports, Object module) {
exports.Set("main", Function::New(env, main(2,{"test","test2"})));
}
NODE_API_MODULE(addon, Init)
besides the fact that you cannot build argv to pass to main like that, you are trying to invoke main and pass its result as second argument to Function::New, while Function::New wants some callable type (e.g. a function pointer) to register as handler for the export named main! Copying from the Function::New documentation:
/// Callable must implement operator() accepting a const CallbackInfo&
/// and return either void or Value.
So, as a simple example, you could export your main as a parameterless JS function that returns nothing (undefined, I guess?) by registering a callback like this:
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)
Finally, as others said, technically in C++ main is somewhat magic - it's undefined behavior to invoke it from inside the program; in practice, on any platform that I know of that can also run node.js, main is a perfectly regular function that happens to be invoked by the C runtime at startup, so I don't think that this will cause you any problem.
Notes
So, you could say it's a NULL-terminated array of NUL-terminated character arrays. Notice that here NULL = null pointer; NUL = string terminator, i.e. '\0'.
This question already has answers here:
C++ : Meaning of const char*const*
(5 answers)
Closed 6 years ago.
I'm working on simulating computer networks using "NS2 Simulator". I don't really understand why we should use const char* const* argv instead of char *?
Can I use char * instead of that? There are many QA about this subject but I've confused about that. Don't mark this question as "Duplicate", please .
why we use const char* const* argv in the function below? is this a rule in c++ standard? can i use either string or char ** instead of that?
Function Connector::command.
//~ns/common/connector.cc
int Connector::command(int argc, const char*const* argv)
{
Tcl& tcl = Tcl::instance();
...
if (argc == 3) {
if (strcmp(argv[1], "target") == 0) {
...
target_ = (NsObject*)TclObject::lookup(argv[2]);
...
}
...
}
return (NsObject::command(argc, argv));
}
const char*const* argv means "pointer to constant pointer to constant char". It's not the same as char*. There is a reason for the const modifier, as the argv pointer wont be reassigned, the elements will have to be accessed by subscript.
This makes it safe for the caller to dynamically allocate argv, pass it into command(), and free it later. Otherwise, if you point a pointer elsewhere before it is freed, then you've leaked the memory that it used to point to.
const char* const* argv creates two levels of indirection - first level is a const pointer to a const char, and second level is a pointer to the const pointer.
The programmer is allowed to const qualify arguments how they see fit. The benefit of this signature:
void func(const char* const* argv);
...is that it will accept argument arrays (of the type passed to main() or exec()), with any const qualification.
So all these are acceptable:
int main(int, char** argv)
{
func(argv);
}
int main(int, const char** argv)
{
func(argv);
}
int main(int, char* const* argv)
{
func(argv);
}
int main(int, const char* const* argv)
{
func(argv);
}
So if you are writing a function to accept argument array parameters (that your function will not modify) then its probably the best signature to select.
why we should use "const ... argv" instead of "char *" ?
The 'const' is from you, the programmer, commanding the compiler to inform you when the code you write tries to modify argv.
can i use char * instead of that?
Possibly, and sometimes it does not matter. But if you mistakenly modify argv (or whatever the const var name is), then the compiler won't let you know you made a mistake, and the result may be something you do not want, even UB.
I'm making the assumption that the array of strings passed into the main function as argv in void main( int argc, char* argv[] ) remains in scope for the duration of the application.
My question is therefore whether it is possible, using boost::program_options to get a pointer to the actual element in argv which represents a particular option.
That is, rather than allocating a std::string when parsing, it is possible to just get a pointer to the start of a string option value.
I've an issue with passing argv to a function. Basically, I want to pass &argv[1] to the function and work from that. However, I don't understand why the following does work:
void fun(char**&argv, const int& argc);
int main(int argc, char** argv)
{
fun(++argv, --argc);
return 0;
}
yet the following doesn't work:
void fun(char**&argv, const int& argc);
int main(int argc, char** argv)
{
fun(&argv[1], --argc);
return 0;
}
Prototype:
void myfunc (char **argv, int argc)
Example usage:
myfunc (argv, argc)
If you wanted to pass ONLY one string (argv[1]):
void myfunc (char *arg, int argc)
...
myfunc (argv[1], argc)
And if you wanted to pass an array of strings starting at argv[1]:
void myfunc (char **arg, int argc)
...
myfunc (&argv[1], argc)
The error I get when I try this is that argv[1] is a temporary value and you can't assign that to a non-const reference. If you instead do this:
void fun( char** const&argv, const int& argc);
Then either ++argv or &argv[1] will work.
Obviously, if you planned to actually change the value of argv itself, this won't work, but I presume that you aren't planning to do this since you're not passing a reference to argv itself but rather to the memory location of the second entry in argv.
The reason that the first one works and the second doesn't is that the ++ operator at the front modifies the variable and then returns not just its value after the modification, but the variable itself. As a result, the variable can then be passed into fun as a reference. But the &argv[1] is just the value of a memory location. It's a computed value, not a variable in its own right, so it can't be passed in as a non-const reference.
If you're planning to try to change the value of argv itself (to point it to a different array of character arrays), then &argv[1] doesn't work for that anyway, since it's not argv. ++argv, however, is argv, just after it's had its value adjusted.
You could also handle all of this without references at all, which would make things much easier, but that's up to you. If it were my code, though, I wouldn't be using references here. The const reference to an int could just be passed by value (which would be easier) and passing a reference to a double pointer doesn't save you any null checking (as it could still well be null). So there isn't much point to it. But if you like your code to be complex, feel free.
This question already has answers here:
Closed 11 years ago.
Possible Duplicates:
main(int argc, char *argv[])
Main's Signature in C++
If i write:
int main(int argc, char** argv)
i get proper commandline input.
What would happen if i wrote say,
int main(int foo, double fooDouble, fooType FooVar)
Is this OS-dependent or does it depend on the compiler?
Given that it does compile, it will still only be called with the argc and argv arguments.
So your fooDouble will get the pointer value of argv, and FooVar will get whatever value is in that register/stack space used for that argument position (which may not have been initialized by the callee, so it may hold any undefined value).
This code doesn't even have to compile. If it does, undefined behaviour may occur.
The effect of adding a third (or fourth, or fifth...) argument to main indeed depends on the operating system. For instance, on Windows (and I believe on Unix as well) you can have a third argument which grants access to the environment variables:
int main( int argc, char **argv, char **env )
The C standard (BS ISO/IEC 9899:1999) gives two alternatives for main:
int main(void) { /* ... */ }
and
int main(int argc, char *argv[]) { /* ... */ }
It also allows equivalents, so an argv of char ** argv for example. Additional arguments are "neither blessed nor forbidden by the Standard". Such addtions will be compiler and runtime (not operating system) specific.
The arguments are passed by the C runtime, which calls main(). Passing any other type would be problematic on general environments like Windows and UNIX, so quite how you would expect to pass a double or fooType is beyond me.
Invoking a program from either a command-line or using interfaces like execve (UNIX) or CreateProcess (Win32) involves passing zero delimited strings. In theory you could hack it to pass a binary value and then cast it in main, provided it does not contain a '\0' anywhere except at the end, which would be challenging.
EDIT: it occurs to me that you can call main() from within your program - the well known obvuscated C code "The twelve days of Christmas" does this. In this case there is no reason why you can pass anything the prototype allows.