Open Chihpin opened 5 years ago
So, does that work?
You could also do it with the getline()
function:
getline(result_buf, 1024, fp);
@holzschu I'm sorry I didn't describe it clearly. The piece of code in my question doesn't work for realtime print
I hit a breakpoint and found it blocked on this line of code
fp = ios_popen(command, "r");
It took a few seconds to continue., so getline()
is not work well.
Then I tried to change the internal implementation of ios_popen
void ios_popen2(const char* inputCmd, const char* type, FILE **output) {
// Save existing streams:
int fd[2] = {0};
const char* command = inputCmd;
// skip past all spaces
while ((command[0] == ' ') && strlen(command) > 0) command++;
// TODO: skip past "/bin/sh -c" and "sh -c"
if (pipe(fd) < 0) { return; } // Nothing we can do if pipe fails
// NOTES: fd[0] is set up for reading, fd[1] is set up for writing
// fpout = fdopen(fd[1], "w");
// fpin = fdopen(fd[0], "r");
if (type[0] == 'w') {
// open pipe for reading
child_stdin = fdopen(fd[0], "r");
// launch command:
*output = fdopen(fd[1], "w");
ios_system(command);
} else if (type[0] == 'r') {
// open pipe for writing
// set up streams for thread
child_stdout = fdopen(fd[1], "w");
// launch command:
*output = fdopen(fd[0], "r");
ios_system(command);
}
// return NULL;
}
And then I call this in my app
__block FILE *fp = NULL;
__block BOOL end_flag = NO;
dispatch_async(dispatch_get_global_queue(0, 0), ^{
char result_buf[MAXLINE];
fpos_t pos = 0;
while(1)
{
if (fp != NULL) {
fsetpos(fp, &pos);
if (fgets(result_buf, sizeof(result_buf), fp) != NULL) {
fgetpos(fp, &pos);
if('\n' == result_buf[strlen(result_buf)-1])
{
result_buf[strlen(result_buf)-1] = '\0';
}
output([NSString stringWithFormat:@"%s", result_buf], NO);
}
}
if (end_flag) {
break;
}
sleep(0.5);
}
});
ios_popen2(input.UTF8String, "r", &fp);
end_flag = YES;
In this way, the real-time printout is realized. It's fantastic!
I don't know much about ios_system
framework.
emmm..... may I ask if there are any danger in my solution?
Ah, now I understand the question.
Yes, by default, ios_system
commands run in the foreground if they are the first command to be called. Meaning the command runs entirely, then gives back control to the app. The solution to have interactive communication between the command and the application is to run them in queues or threads, as you have done.
You could (probably) also make it work by sending the ios_popen2
command in an async queue, and have the reading in the main loop.
You could also simplify your code with:
thread_stdout = fdopen(fd[1], "w");
thread_stdin = fdopen(fd[0], "r");
ios_system(command);
and then listen to thread_stdout
in the async
queue. By default, ios_system
commands write their standard output to a stream called thread_stdout
and listen to a stream called thread_stdin
.
@holzschu I see. thx
I am a newbie about this.
Here's my code
It waits for the command to finish before printing the output together