别管那些“为什么?”、“没用了?”和“别费心了”的评论。我想用clang在另一个程序中编译一个程序。我可以创建NSTask并设置参数,如果文件存在,它将工作,(即.没有流),并写入物理文件。我还没能得到我真正想要的东西,那就是同时使用流作为输入和输出。我知道如果您使用-xc和-选项,clang和gcc都允许编译标准输入,但无法使用管道实现该功能。我也不确定如何将clang的输出重定向到文件句柄或流。
下面是编译它并在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];我已经尝试过对输入流使用这个:
/* on pipe creation*/
dup2([[inPipe fileHandleForReading] fileDescriptor], STDIN_FILENO);
NSFileHandle* curInputHandle = [inPipe fileHandleForWriting];
/* tried before launch and after, no output just sits */
[curInputHandle writeData:[NSData dataWithContentsOfFile:filename]];有时,我假设当管道关闭而NSTask仍然存在时,输出文件就会创建并运行。这让我认为clang只是在等待stdin关闭。有没有办法在读取数据后关闭管道?
对于输出,我尝试使用NSPipe的fileHandleForWriting作为-o的参数,这会给出[NSConcretePipe fileSystemRepresentation]无法识别选择器的错误。我尝试使用stdout的文件描述符来创建一个文件句柄,但出现了相同的错误。我不知道有什么命令行参数可以重定向它。我尝试过使用|来重定向,但是没能让它工作。如果有什么unix魔法可以重定向它,我可以把stdout复制到我想要的任何地方。
那么,当所有数据都被读取时,有没有办法关闭管道?和重定向clangs输出?如果有任何其他方法可以更容易或更干净地完成相同的事情,我对任何实现都持开放态度。在这两个项目上的任何帮助都是非常好的。
发布于 2012-06-08 09:39:32
我不清楚你的问题是什么,也不清楚你尝试过什么。但是,如果您要使用通知从主线程上的管道读取输出,并希望也写入管道,则可以选择写入另一个线程中的管道。下面的代码基于您的代码,使用GCD完成此操作。为简单起见,本例将二进制文件存放在/tmp中:
// send a simple program to clang using a 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 the code, close the file (pipe in this case)
});
}
// read the output from clang and dump to 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 an NSTask, reading output via notifications
// and providing input via an 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]];
}https://stackoverflow.com/questions/10907903
复制相似问题