How do I put arguments into a function at runtime?

So I am using execlp in my C ++ program. execlp has the form "int execlp (const char * file, const char * arg0, ..., const char * argn)", which means that it can take any number of arguments. I just want to know that there is a way to include arguments inside this function at runtime? Since the arguments are user supplied, there is no way for me to know the exact number of arguments. Of course, I can pick a ridiculously large number from the start, but that won't be very effective. I want a more efficient way that allows me to enter arguments at runtime.

+3


source to share


2 answers


If you do not need to use execlp

, execv

or execvp

are the best features for your requirement.

From http://linux.die.net/man/3/execlp



The execv () , execvp (), and execvpe () functions provide an array of pointers to null terminated strings that represent the list of arguments available to the new program. The first argument, by convention, must point to the filename associated with the executable. The array of pointers must be terminated with a NULL pointer.

+3


source


I am assuming you are using Linux or some other POSIX system.

You explicitly need R.Sahu's answer to use functions such as execv (3) , which takes an array of execve (2) syscall arguments. You can allocate this array in C heap with malloc (3) or friends ( calloc

). If the coding is in C ++ you should use new

.

For example, the useless, that piece of code that performs /bin/echo

an array of arguments 1

, 2

, .... nargs, which int nargs;

is strictly positive.

Variant in C99

assert(nargs>0);
char** myargs = malloc ((nargs+2)*sizeof(char*));
if (!myargs) { perror("malloc myargs"); exit(EXIT_FAILURE); };
myargs[0] = "echo";
for (int ix=0; ix<nargs; ix++)
   { char buf[32];
     snprintf(buf,sizeof(buf),"%d",ix);
     myargs[ix+1] = strdup(buf);
     if (!myargs[ix+1]) { perror("strdup"); exit(EXIT_FAILURE); };
   }
myargs[nargs+1] = NULL;
execv("/bin/echo", myargs);
perror("exec echo failed");
exit(EXIT_FAILURE);

      

In C ++, you code for example char**myargs = new char*[nargs+2]

;



In general, you will need a later free

(in C ++, use delete

) heap of allocated memory. This is really not needed here, since it is execv

not returned. However, in other cases (for example, when using fork

before execv

, so the parent process continues later waitpid

), you need a loop for free

each individual element (result strdup

), then you need the free

whole array myargs

.

As for the general question of calling an arbitrary (time-known) arbitrary signature function, this is not possible in the normal C99 standard, but you can use some libraries (with multiple assemblers or machine code inside them) like libffi

In genuine C ++ 11, you still need the array argument execv

as an array char*

. You can use (as an intermediate step) some std::vector<std::string>

, but you will need to at least convert it to std::vector<char*>

and then pass the data to execve

. Read about std :: string (and its member function c_str

) and std :: vector (and its member function data

). You can try something like:

 assert (nargs>0);
 std::vector<std::string> vecstr;
 vecstr.resize(nargs+2);
 vecstr[0] = "echo";
 for (int ix=0; ix<nargs; ix++) vecstr[ix+1] = std::to_string(ix+1);
 std::vector<const char*> vecargs;
 vecargs.resize(nargs+2,nullptr); 
 std::transform(vecstr.begin(), vecargs.begin(), 
                  [](const std::string&s) { return s.c_str(); });
 vecargs[nargs+1] = nullptr;
 execv("/bin/echo", vecargs.data());
 throw std::runtime_error(std::string{"exec failure:"}+strerror(errno));

      

Note that it execv

can fail, in particular, when the argument array is too large; the limit is usually a few hundred thousand elements, but it can be much less.

+2


source







All Articles