Pregunta

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 ?

¿Fue útil?

Solución

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.

Otros consejos

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:

  1. what is arg? is it defined?
  2. can arg be NULL?
  3. is arg a pointer or an array?

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.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top