objective c - Clang NSTask with streams -
never-mind "why?","useless?", , "don't bother" comments. want compile program inside program using clang. can create nstask
, set arguments , work if file exists, (ie. no stream), , writes physical file. haven't been able use streams both input , output. know both clang , gcc allow compiling stdin if use -xc , - options unable implement feature using pipes. not sure how redirect clang's output file handle or stream.
here code have compiles , generates correct output in outfile
task = [[nstask alloc] init]; nspipe* outputpipe = [[nspipe alloc] init]; [task setstandardoutput:outputpipe ]; [task setstandarderror: [task standardoutput]]; nspipe* inpipe = [nspipe pipe]; [task setstandardinput:inpipe]; [task setlaunchpath:@"/usr/bin/clang"]; nsstring* outfile= [nsstring stringwithformat:@"%@.out",[[filename lastpathcomponent] stringbydeletingpathextension]]; //[data writetofile:@"file.c" atomically:yes]; [task setarguments:[nsarray arraywithobjects:filename,@"-s",@"-o",outfile,nil]]; [[nsnotificationcenter defaultcenter] addobserver:self selector:@selector(getdata:) name: nsfilehandlereadcompletionnotification object: [[task standardoutput] filehandleforreading]]; [[[task standardoutput] filehandleforreading] readinbackgroundandnotify]; [task launch];
i have tried using input stream:
/* on pipe creation*/ dup2([[inpipe filehandleforreading] filedescriptor], stdin_fileno); nsfilehandle* curinputhandle = [inpipe filehandleforwriting]; /* tried before launch , after, no output sits */ [curinputhandle writedata:[nsdata datawithcontentsoffile:filename]];
sometimes, assume when pipe closes while nstask still in existance output file created , run. makes me think clang waiting stdin close. there way close pipe when data has been read?
for output have tried use nspipe's filehandleforwriting parameter of -o, gives error of [nsconcretepipe filesystemrepresentation]
unrecognized selector. have tried creating file handle file descriptor of stdout same error. don't know of command line argument redirects it. i've tried using |
redirect haven't been able work. if there unix magic redirect can dup stdout anywhere want.
so there way close pipe when data read? , redirect clangs output? if there other way accomplish same thing easier or cleaner open implementation. on these 2 items great.
it not clear me problem or you've tried. however, if going read output pipe on main thread using notifications , wish write pipe 1 option write pipe in thread. code below, based on code, using gcd. simplicity in example binary deposited in /tmp:
// send simple program clang using gcd task - (void)providestdin:(nsfilehandle *)stdinhandle { dispatch_queue_t aqueue = dispatch_get_global_queue(dispatch_queue_priority_default, 0); dispatch_async(aqueue, ^{ [stdinhandle writedata:[@"int main(int argc, char **argv)\n" datausingencoding:nsutf8stringencoding]]; [stdinhandle writedata:[@"{\n" datausingencoding:nsutf8stringencoding]]; [stdinhandle writedata:[@" write(1, \"hello\\n\", 6);\n" datausingencoding:nsutf8stringencoding]]; [stdinhandle writedata:[@"}\n" datausingencoding:nsutf8stringencoding]]; [stdinhandle closefile]; // sent code, close file (pipe in case) }); } // read output clang , dump console - (void) getdata:(nsnotification *)notifcation { nsdata *dataread = [[notifcation userinfo] objectforkey:nsfilehandlenotificationdataitem]; nsstring *textread = [[nsstring alloc] initwithdata:dataread encoding:nsutf8stringencoding]; nslog(@"read %3ld: %@", (long)[textread length], textread); } // invoke clang using nstask, reading output via notifications // , providing input via async gcd task - (void)applicationdidfinishlaunching:(nsnotification *)anotification { nstask *task = [nstask new]; nspipe *outputpipe = [nspipe new]; [task setstandardoutput:outputpipe]; [task setstandarderror:outputpipe]; nsfilehandle *outputhandle = [outputpipe filehandleforreading]; nspipe* inpipe = [nspipe pipe]; [task setstandardinput:inpipe]; [task setlaunchpath:@"/usr/bin/clang"]; [task setarguments:[nsarray arraywithobjects:@"-o", @"/tmp/clang.out", @"-xc",@"-",nil]]; [[nsnotificationcenter defaultcenter] addobserver:self selector:@selector(getdata:) name:nsfilehandlereadcompletionnotification object:outputhandle]; [outputhandle readinbackgroundandnotify]; [task launch]; [self providestdin:[inpipe filehandleforwriting]]; }
Comments
Post a Comment