void pyrun’ has incomplete type - c++

the current algorithm is working in boost, but it isn't working in pybind11
int main(int argc, char **argv)
{
try
{
// retrieve the filename from command line argument if there is one
auto filename = QString();
if (argc > 1)
{
filename = argv[1];
}
initPalette();
QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8"));
srand48(time(NULL))
Py_Initialize();
PySys_SetArgvEx(0, NULL, 0);
// Disable the SIGINT handler in Python so we can Ctrl-C to exit
{
namespace py = pybind11;
auto main = py::module::import("__main__").attr("__dict__");
auto pyrun = py::exec("import signal; signal.signal(signal.SIGINT, signal.SIG_DFL)",main);
}

Related

Passing std::string as input to getopt()

I have a program that basically looks like this:
#include <iostream>
#include <unistd.h> // getopt
#include <vector>
#include <string>
#include <list>
#include <sstream>
using namespace std;
//a parameter structure to store parameters provided through console
typedef struct pairwise_param {
double alpha;
double beta;
} param;
//parse the parameter values
void param_getopt(param *pm, int argc, char **argv) {
int opt;
while((opt = getopt(argc, argv, "a:b:")) != -1) {
switch(opt) {
case 'a':
pm->alpha = atof(optarg);
break;
case 'b':
pm->beta = atof(optarg);
break;
}
}
}
int main(int argc, char* argv[]) {
//initialize param structure
param pm;
//pass command line arguments to param
param_getopt(&pm, argc, argv);
//do something to the parameters
std::cout << "Alpha: " << pm.alpha << std::endl;
std::cout << "Beta: " << pm.beta << std::endl;
return(0);
}
By making a header file and changing the main function to someother name, e.g. int main(int argc, char* argv[]) -> int maincomp(int argc, char* argv[]) I want to call the new function maincomp() from another program but instead of passing command line arguments I want to pass the arguments through a std::string.
I thought I could do something like this but it does seem to have some issues with getopt() that Im not entirely certain why. Currently anything that is written to console using for example std::cout after getopt() is called will not be displayed. It looks like what is passed to getopt() currently is not correctly type converted. My question therefore is how should one type cast a std::string to conform to the char * const argv[] input requirement of getopt(int argc, char * const argv[])?
int main(int argc, char* argv[]) {
//create string and pass it to maincomp
std::string cmd = "-a2.3 -b3.2";
std::istringstream ss(cmd);
std::string arg;
std::list<std::string> ls;
std::vector<char*> newargv;
while (ss >> arg) {
ls.push_back(arg);
newargv.push_back(const_cast<char*>(ls.back().c_str()));
}
newargv.push_back(0);
int out = maincomp(newargv.size(), &newargv[0]);
return(out);
}
The entire code:
https://onlinegdb.com/tjMC-LwiP
Using wordsexp.h solved the issue by parsing the string correctly for getopt().
Essentially:
//create string and pass it to maincomp
std::string cmd = "-a2.3 -b3.2";
//convert string with wordexp
wordexp_t newargv;
newargv.we_offs = 1;
wordexp(cmd.c_str(), &newargv, WRDE_DOOFFS);
//create a new argc
int newargc = newargv.we_wordc + newargv.we_offs;
//pass to maincomp function
int out = maincomp(newargc, newargv.we_wordv);
Full code:
#include <iostream>
#include <unistd.h> // getopt
#include <vector>
#include <string>
#include <wordexp.h>
typedef struct pairwise_param {
double alpha; double beta;
} param;
void param_getopt(param *pm, int argc, char **argv){
int opt;
while((opt=getopt(argc,argv,"a:b:"))!=-1){
switch(opt){
case 'a': pm->alpha = atof(optarg); break;
case 'b': pm->beta = atof(optarg); break;
}
}
}
int maincomp(int argc, char* argv[]){
//initialize param structure
param pm;
//pass command line arguments to param
param_getopt(&pm, argc, argv);
std::cout << "Alpha: " << pm.alpha << std::endl;
std::cout << "Beta: " << pm.beta << std::endl;
return(0);
}
int main(int argc, char* argv[]) {
//create string and pass it to maincomp
std::string cmd = "-a2.3 -b3.2";
//convert string with wordexp
wordexp_t newargv;
newargv.we_offs = 1;
wordexp(cmd.c_str(), &newargv, WRDE_DOOFFS);
int newargc = newargv.we_wordc+newargv.we_offs;
//pass to maincomp function
int out = maincomp(newargc, newargv.we_wordv);
return(out);
}
Produces the expected output:
Alpha: 2.3
Beta: 3.2

How to know if a gflag was provided in the command line

I use gFlags in a c++ application, to collect command line flags:
DEFINE_string("output_dir", ".", "existing directory to dump output");
int main(int argc, char** argv) {
gflags::ParseCommandLineFlags(argc, argv, true);
...
}
This flag has a default value, so the user may choose not to provide the same on the command line. Is there any API in gFlags to know if the flag was supplied in the command line? I did not find any, so using the following hack:
DEFINE_string("output_dir", ".", "existing directory to dump output");
static bool flag_set = false;
static void CheckFlags(const int argc, char** const argv) {
for (int i = 0; i < argc; i++) {
if (string(argv[i]).find("output_dir") != string::npos) {
flag_set = true;
break;
}
}
}
int main(int argc, char** argv) {
CheckFlags(argc, argv);
gflags::ParseCommandLineFlags(argc, argv, true);
if (flag_set) {
// blah.. blah..
}
return 0;
}
After studying the gflags code in detail, I found an API gflags::GetCommandLineFlagInfoOrDie(const char* name) which returns CommandLineFlagInfo, which contains a boolean flag named is_default which is false if the flag was provided in the command line:
struct CommandLineFlagInfo {
std::string name; // the name of the flag
//...
bool is_default; // true if the flag has the default value and
// has not been set explicitly from the cmdline
// or via SetCommandLineOption
//...
};
So I do not need the hack any more:
DEFINE_string("output_dir", ".", "existing directory to dump output");
static bool flag_set = false;
int main(int argc, char** argv) {
CheckFlags(argc, argv);
gflags::ParseCommandLineFlags(argc, argv, true);
bool flag_not_set = gflags::GetCommandLineFlagInfoOrDie("output_dir").is_default;
if (!flag_not_set) {
// blah.. blah..
}
return 0;
}

Open TTY to use with execlp and dup

I am trying to create a minimal code to use pipe/fork/execlp.
So far so good, I am using execlp with bash -c, so if I do.
echo asd |./a.out cat
> asd
So it is working as expected.
But if I try to use anything that needs a TTY, it does not work.
Like ./a.out vim, I get "Vim: Warning: Input is not from a terminal"
And the vim that was open does not works as expected.
I tried to find on the internet an example on how to open a TTY, the only one that I found was:
http://www.danlj.org/lad/src/minopen.c
My Code, so far is:
#include <iostream>
#include <cstdio>
#include <string.h>
#include <cstdlib>
#include <unistd.h>
#include <sys/wait.h>
typedef struct pCon{
int fout[2];
int fin[2];
int fd[2];
int pid1, pid2;
} connectionManager;
std::string command = "";
/*
* Implementation
*/
void childFork(connectionManager *cm);
int main(int argc, char *argv[]) {
int size;
if(argc < 2) exit(1);
else command = argv[1];
connectionManager *cm = new connectionManager;
pipe(cm->fd);
if((cm->pid1 = fork()) == -1)exit(1);
if (cm->pid1 == 0)
{
const unsigned int RCVBUFSIZE = 2000;
char echoString[RCVBUFSIZE];
while((size = read(fileno(stdin),echoString,RCVBUFSIZE)) > 0)
write(cm->fd[1], echoString, size);
close(cm->fd[1]);
}
else
childFork(cm);
return 0;
}
void childFork(connectionManager *cm){
char *buffer = new char[2000];
int size;
close(cm->fd[1]);
dup2(cm->fd[0], 0);
close(cm->fd[0]);
pipe(cm->fout);
if((cm->pid2 = fork()) == -1)exit(1);
if (cm->pid2 == 0)
{
close(cm->fout[0]);
int returnCode = execlp("bash", "bash", "-c", command.c_str(), NULL);
if(returnCode!=0)
std::cerr << "Error starting the bash program" << std::endl;
}
else
{
close(cm->fout[1]);
while((size = read(cm->fout[0], buffer, 2000 )) > 0 )
write(fileno(stdout), buffer, size);
}
}
I tried to keep the minimal necessary code to make it work.
Is there any way to implement TTY on this code, I know that does not seems to be such trivial task.
Can someone help me with that?
I also tried to open the tty and dup it, but no luck so far.
Try to use pseudo terminal. You can use opentty. For your purpose you can use forkpty which combines pty with fork. I've created a small example for you. About the same as your program, just it works. I've kept it simple, so I don't handle the terminal control characters.
#include <pty.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <sys/select.h>
int main(int argc, char *argv[])
{
if (argc<1) return 1;
int master;
pid_t pid = forkpty(&master, NULL, NULL, NULL); // opentty + login_tty + fork
if (pid < 0) {
return 1; // fork with pseudo terminal failed
}
else if (pid == 0) { // child
char *args[] = { argv[1], argv[2], NULL }; // prg + 1 argument
execvp(argv[1], args); // run the program given in first param
}
else { // parent
struct termios tios;
tcgetattr(master, &tios);
tios.c_lflag &= ~(ECHO | ECHONL);
tcsetattr(master, TCSAFLUSH, &tios);
while(1) {
fd_set read_fd, write_fd, err_fd;
FD_ZERO(&read_fd);
FD_ZERO(&write_fd);
FD_ZERO(&err_fd);
FD_SET(master, &read_fd);
FD_SET(STDIN_FILENO, &read_fd);
select(master+1, &read_fd, &write_fd, &err_fd, NULL);
if (FD_ISSET(master, &read_fd))
{
char ch;
int c;
if (c=read(master, &ch, 1) != -1) // read from program
write(STDOUT_FILENO, &ch, c); // write to tty
else
break; // exit when end of communication channel with program
}
if (FD_ISSET(STDIN_FILENO, &read_fd))
{
char ch;
int c=read(STDIN_FILENO, &ch, 1); // read from tty
write(master, &ch, c); // write to program
}
}
}
return 0;
}
For compiling use -lutil .
While running a new tty device appears in /dev/pts .
vim accepts it as a terminal.

c++ default argv if no parameter is parsed in console

i would like to give my file a default argv, if none is given in the console. It doesn't work cause of duplicate parameter names.
if no parameter is given, i would like to use a fixed filename in the same folder.
int main(int argc, char* argv[], char* argv[1]="test.ps1")
{
std::string target = _T(argv[1]);
std::string temp= std::string("powershell.exe -command \"")+target +std::string("\"");
ShellExecuteA(0, "runas", "powershell.exe", temp.c_str, "", SW_HIDE);
}
int main(int argc, char **argv) {
std::string const default_file = "test.ps1";
std::string file = (argc < 2) ? default_file : argv[1];
doSomethingWithFile(file);
}

How to copy a file from a folder to another folder

How do I copy a file from one folder to another folder using C++?
This should be the minimal code required:
#include <fstream>
// copy in binary mode
bool copyFile(const char *SRC, const char* DEST)
{
std::ifstream src(SRC, std::ios::binary);
std::ofstream dest(DEST, std::ios::binary);
dest << src.rdbuf();
return src && dest;
}
int main(int argc, char *argv[])
{
return copyFile(argv[1], argv[2]) ? 0 : 1;
}
it glosses around some potentially complicated issues: error handling, filename character encodings... but could give you a start.
With std::filesystem::copy_file from C++17:
#include <exception>
#include <filesystem>
#include <iostream>
namespace fs = std::filesystem;
int main()
{
fs::path sourceFile = "path/to/sourceFile.ext";
fs::path targetParent = "path/to/target";
auto target = targetParent / sourceFile.filename(); // sourceFile.filename() returns "sourceFile.ext".
try // If you want to avoid exception handling, then use the error code overload of the following functions.
{
fs::create_directories(targetParent); // Recursively create target directory if not existing.
fs::copy_file(sourceFile, target, fs::copy_options::overwrite_existing);
}
catch (std::exception& e) // Not using fs::filesystem_error since std::bad_alloc can throw too.
{
std::cout << e.what();
}
}
I've used std::filesystem::path::filename to retrieve the source filename without having to type it manually. However, with std::filesystem::copy you can omit passing the filename to the target path at all:
fs::copy(sourceFile, targetParent, fs::copy_options::overwrite_existing);
Change the behaviour of both functions with std::filesystem::copy_options.
If you're willing to use the Boost C++ libraries, take a look at filesystem::copy_file().
Here's a previous question covering copy_file():
How to use copy_file in boost::filesystem?
This is how you can do this.
include c++ library <windows.h>
Use function
CopyFile("d:/folder1/file.exe","d:/folder2/file.exe",true)
All Done :)
The code below will copy all the file from one directory to another.
Its working code in C++
#include <windows.h>
/*
BOOL Copy(char r_szPath[1024], char r_szDir[1024])
{
char l_szTemp[2048] = {0};
sprintf(l_szTemp,"%s\%s"r_szPath,r_szDir);
if(IsDirectory(
}*/
#include <stdio.h>
#include<conio.h>
BOOL __Copy(char r_szSrcPath[1024],char r_szDesPath[1024])
{
WIN32_FIND_DATA FindFileData;
HANDLE hFind;
char l_szTmp[1025] = {0};
memcpy(l_szTmp,r_szSrcPath,1024);
char l_szSrcPath[1025] = {0};
char l_szDesPath[1025] = {0};
memcpy(l_szSrcPath,r_szSrcPath,1024);
memcpy(l_szDesPath,r_szDesPath,1024);
char l_szNewSrcPath[1025] = {0};
char l_szNewDesPath[1025] = {0};
strcat(l_szTmp,"*");
hFind = FindFirstFile(l_szTmp, &FindFileData);
if(hFind == NULL) return FALSE;
do
{
if(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
if(strcmp(FindFileData.cFileName,"."))
{
if(strcmp(FindFileData.cFileName,".."))
{
printf ("The Directory found is %s<BR>, FindFileData.cFileName);
sprintf(l_szNewDesPath,"%s%s\",l_szDesPath,FindFileData.cFileName);
sprintf(l_szNewSrcPath,"%s%s\",l_szSrcPath,FindFileData.cFileName);
CreateDirectory(l_szNewDesPath,NULL);
__Copy(l_szNewSrcPath,l_szNewDesPath);
}
}
}
else
{
printf ("The File found is %s<BR>, FindFileData.cFileName);
char l_szSrcFile[1025] = {0};
char l_szDesFile[1025] = {0};
sprintf(l_szDesFile,"%s%s",l_szDesPath,FindFileData.cFileName);
sprintf(l_szSrcFile,"%s%s",l_szSrcPath,FindFileData.cFileName);
BOOL l_bRet = CopyFile(l_szSrcFile,l_szDesFile,TRUE);
}
}
while(FindNextFile(hFind, &FindFileData));
FindClose(hFind);
return TRUE;
}
int main(int argc, char *argv[])
{
__Copy("C:\fcdb\","E:\sandy\");
getch();
return 0;
}