Reputation: 5301
I am trying to make a copy of char *argv[]
so that i can pass them to a function that takes char**
. First i have to remove some flags from the original argv
:
int main(int argc, char* argv[]) {
::MessageBox(0,"Stopped at the entry point",0,0);
std::string inChannelParam = "--ipc-in-channel";
std::string outChannelParam = "--ipc-out-channel";
std::string inChannelName;
std::string outChannelName;
std::vector<std::string> argv_copy;
for(int i=0; i<argc; ++i) {
if(inChannelParam == argv[i]) {
if(++i < argc) {
inChannelName = argv[i];
continue;
}
} else if(outChannelParam == argv[i]) {
if(++i < argc) {
outChannelName = argv[i];
continue;
}
}
argv_copy.push_back(argv[i]);
}
std::vector<std::unique_ptr<char[]> > argv_copy_char;
for(int i=0;i<argv_copy.size();++i) {
argv_copy_char.push_back(std::unique_ptr<char[]>(new char[argv_copy[i].size()+1]));
memcpy(argv_copy_char[i].get(), &argv_copy[i][0], argv_copy[i].size());
argv_copy_char[i][argv_copy[i].size()] = '\0';
}
// what should i put here ?? --------------------vvv
v8::V8::SetFlagsFromCommandLine(&argc, &(argv_copy_char[0].get()), true);
I tried both string and char [] based approach. It is giving compiler errors :
error C2102: '&' requires l-value
Using &(argv_copy_char[0]._Myptr)
gives me Runtime errors at
if (arg != NULL && *arg == '-') {
in flags.cc
.
The signature of the function SetFlagsFromCommandLine is
SetFlagsFromCommandLine (int *argc, char **argv, bool remove_flags)
.
What should i do ?
Upvotes: 0
Views: 1250
Reputation: 153899
SetFlagsFromCommandLine
looks like a fairly special function
to me, in that it seems to expect argc
and argv
as
arguments, and modifies them (presumably by removing options).
If at all possible, I would call it first, with argc
and
argv
, and do my special handling after. The modification
probably takes place in the form of shifting pointers in argv
down, which means that any solution using std::vector
will
require some additional handling after calling the function.
If you cannot change the order of handling (e.g. because
--ipc-in-channel
and its argument might be extracted by
SetFlagsFromCommandLine
), then you'll probably need something
like the following (after you've parsed your args):
std::vector<char*> tmp;
for ( auto current = argv_copy.begin();
current != argv_copy.end();
++ current ) {
tmp.push_back( current->empty ? "" : &(*current)[0] );
}
int argc_copy = tmp.size();
SetFlagsFromCommandLine( &argc_copy, &tmp[0] );
if ( argc_copy != argv_copy.size() ) {
auto dest = argv_copy.begin();
auto src = tmp.begin();
while ( dest != argv_copy.end() ) {
if ( (*src)[0] == '\0' ) {
if ( *dest != "" ) {
++ dest ;
} else {
while ( dest != argv_copy.end() && *dest != "") {
dest = argv.erase( dest );
}
}
} else {
if ( !dest->empty() && &(*dest)[0] == *src ) {
++ dest;
} else {
while( dest != argv_copy.end()
&& (dest->empty() || &(*dest)[0] != *src) ) {
dest = argv.erase( dest );
}
}
}
}
assert( argv_copy.size() == argc_copy );
}
This is just off the top of my head, and probably contains some
errors, but it gives an idea of the effort necessary if you
cannot call SetFlagsFromCommandLine
first.
EDIT:
Alternatively, and although it is a bit of a pain, you can
process argc
and argv
in exactly the same way
SetFlagsFromCommandLine
does internally, without putting them
in an std::vector
:
int dest = 1;
int source = 1;
while ( source != argc ) {
if ( inChannelParam == argv[source] == 0 && source < argc - 1 ) {
inChannelName = argv[source + 1];
source += 2;
} else if ( outChannelPara == argv[source] == 0 && source < argc - 1 ) {
outChannelName = argv[source + 1];
source += 2;
} else {
argv[dest] = argv[source];
++ dest;
++ source;
}
}
argc = dest;
SetFlagsFromCommandLine( &argc, argv );
std::vector<std::string> argv_copy( argv, argv + argc );
It's not fun dealing with char**
et al., but since you need
this format later, it's probably less of a pain than translating
multiple times between the formats.
Upvotes: 1
Reputation: 42085
You have constructed and filled the vector of strings: std::vector<std::string> argv_copy;
but
I don't understand why you have decided to use this vector to create another vector that will hold elements of type unique_ptr<char[]>
:
std::vector<std::unique_ptr<char[]> > argv_copy_char;
Also note that the prototype of v8::V8::SetFlagsFromCommandLine
is:
static void SetFlagsFromCommandLine (int *argc, char **argv, bool remove_flags)
... exposing the vector's internals wouldn't be very lucky idea here, since argv_copy
holds objects of type std::string
... yet the API requires char**
, so what you could do is dynamically allocate and fill a temporary C-style array of pointers to these strings:
// temporary C-style array
int myArgvSize = argv_copy.size();
char* myArgv[] = new char* [myArgvSize];
for (int i = 0; i < myArgvSize; ++i)
myArgv[i] = &argv_copy[i][0];
v8::V8::SetFlagsFromCommandLine(&myArgvSize, myArgv, true);
// cleanup:
delete[] myArgv;
just note that this solution relies on the fact that SetFlagsFromCommandLine
will not modify the length of these strings.
Upvotes: 2
Reputation: 11577
why do SetFlagsFromCommandLine
gets a pointer to integer? is it need to change the integer?i don't see why will you want to pass a pointer to it.
also the problem seems to be in a completely different place, so the code you shared isn't much helpful
finally, look at the line you got the error in. check:
arg
? is it defined?arg
be NULL?arg
a pointer or an array?Upvotes: 1