sheredom / subprocess.h

🐜 single header process launching solution for C and C++
The Unlicense
1.1k stars 97 forks source link

vector<std::string> of commandline args #84

Closed shakfu closed 5 months ago

shakfu commented 5 months ago

I have the need in my c++ program of modifying the command line args given certain conditions. This favors using a vector<std::string> instead of the current approach.

#include <subprocess.h>
#include <initializer_list>
#include <vector>

char *convert(const std::string & s)
{
   char *pc = new char[s.size()+1];
   std::strcpy(pc, s.c_str());
   return pc; 
}

int cmd(std::initializer_list<std::string>  args)
{
    std::vector<char*> vc;
    std::transform(args.begin(), args.end(), std::back_inserter(vc), convert);
    // vc.push_back(NULL);

    struct subprocess_s subprocess;
    int result = subprocess_create(&vc[0], 0, &subprocess);
    if (0 != result) {
        printf("error occurred.");
    };  

    std::cout << "vc.size(): " << vc.size() << std::endl;

    for ( size_t i = 0 ; i < vc.size() ; i++ )
        std::cout << vc[i] << std::endl;

    for ( size_t i = 0 ; i < vc.size() ; i++ )
        delete [] vc[i];

    return 0;
}

The problem I have is that if I push_back(NULL) to add a NULL sentinel I get an error and it doesn't work as expected.. Do I have to modify subprocess.h itself with this approach and just drop the sentinel requirement or is there a way of making something like the above work?

sheredom commented 5 months ago

Can you paste the error you get please?

shakfu commented 5 months ago

Ok, I got it to work eventually. Here's a working version:

#include <initializer_list>
#include <string>
#include <vector>
#include <subprocess.h>

char *convert(const std::string & s)
{
   char *pc = new char[s.size()+1];
   std::strcpy(pc, s.c_str());
   return pc; 
}

int cmd(std::initializer_list<std::string>  args)
{
    std::vector<char*> vc;
    std::transform(args.begin(), args.end(), std::back_inserter(vc), convert);
    // vc.push_back(NULL); // <-- this is actually not required

    struct subprocess_s subprocess;
    int result = subprocess_create(&vc[0], 0, &subprocess);
    if (0 != result) {
        printf("error occurred.\n");
    } else {
        FILE* p_stdout = subprocess_stdout(&subprocess);
        char data[32];
        fgets(data, 32, p_stdout);
        printf("result: %s\n", data);
    }

    // std::cout << "vc.size(): " << vc.size() << std::endl;

    // for ( size_t i = 0 ; i < vc.size() ; i++ )
    //     std::cout << vc[i] << std::endl;

    for ( size_t i = 0 ; i < vc.size() ; i++ )
        delete [] vc[i];

    return 0;
}

int main(int argc, char* argv[])
{
    cmd({"/bin/bash", "--version"});
    return 0;
}
sheredom commented 5 months ago

Nice one!