2011-06-14 8 views
5

के बाद मैं वर्तमान में छेद NSTask, NSPipe, NSFileHandle व्यापार के आसपास मेरे सिर लपेटो करने की कोशिश कर रहा हूँ। तो मैंने सोचा कि मैं एक छोटा सा टूल लिखता हूं, जो संकलित और सी कोड चला सकता है। मैं भी अपने stdout और stdin को एक पाठ दृश्य में रीडायरेक्ट करने में सक्षम होना चाहता था।NSTasks मानक इनपुट करने के लिए लिखें लांच

यहां तक ​​कि मुझे अब तक क्या मिला है। What is the best way to redirect stdout to NSTextView in Cocoa?

NSPipe *inputPipe = [NSPipe pipe]; 
// redirect stdin to input pipe file handle 
dup2([[inputPipe fileHandleForReading] fileDescriptor], STDIN_FILENO); 
// curInputHandle is an instance variable of type NSFileHandle 
curInputHandle = [inputPipe fileHandleForWriting]; 

NSPipe *outputPipe = [NSPipe pipe]; 
NSFileHandle *readHandle = [outputPipe fileHandleForReading]; 
[readHandle waitForDataInBackgroundAndNotify]; 
// redirect stdout to output pipe file handle 
dup2([[outputPipe fileHandleForWriting] fileDescriptor], STDOUT_FILENO); 

// Instead of writing to curInputHandle here I would like to do it later 
// when my C program hits a scanf 
[curInputHandle writeData:[@"123" dataUsingEncoding:NSUTF8StringEncoding]]; 

NSTask *runTask = [[[NSTask alloc] init] autorelease]; 
[runTask setLaunchPath:target]; // target was declared earlier 
[runTask setArguments:[NSArray array]]; 
[runTask launch]; 

NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; 
[center addObserver:self selector:@selector(stdoutDataAvailable:) name:NSFileHandleReadCompletionNotification object:readHandle]; 

यहाँ stdoutDataAvailable विधि

- (void)stdoutDataAvailable:(NSNotification *)notification 
{ 
    NSFileHandle *handle = (NSFileHandle *)[notification object]; 
    NSString *str = [[NSString alloc] initWithData:[handle availableData] encoding:NSUTF8StringEncoding]; 
    [handle waitForDataInBackgroundAndNotify]; 
    // consoleView is an NSTextView 
    [self.consoleView setString:[[self.consoleView string] stringByAppendingFormat:@"Output:\n%@", str]]; 
} 

इस कार्यक्रम ठीक काम कर रहा है और: मैं कोड इस पोस्ट से मेरी stdio रीडायरेक्ट करने के लिए इस्तेमाल किया। यह सी प्रोग्राम को मेरे टेक्स्ट व्यू में स्टडआउट प्रिंट करने और मेरे इनपुट पाइप से "123" पढ़ने के लिए चला रहा है। जैसा कि ऊपर मेरी टिप्पणी में इंगित किया गया है, मैं इनपुट प्रदान करना चाहता हूं, जबकि कार्य की आवश्यकता होने पर कार्य चल रहा है।

तो अब दो प्रश्न हैं।

  1. जैसे ही कोई मेरे इनपुट पाइप से डेटा पढ़ने की कोशिश करता है, अधिसूचना प्राप्त करने का कोई तरीका है?
  2. यदि 1 का उत्तर नहीं है, तो क्या कोई अलग दृष्टिकोण है जिसे मैं कोशिश कर सकता हूं? शायद एनएसटीस्क के अलावा एक वर्ग का उपयोग कर?

कोई भी सहायता, नमूना कोड, अन्य संसाधनों के लिंक की अत्यधिक सराहना की जाती है!

उत्तर

2

मुझे यकीन है कि चाहे आप एक NSPipe पर एक "पुल" का पता लगा सकते नहीं हूँ। मैं एक अस्पष्ट भावना मैं देखने के लिए कि select() या kqueue उपयोग करने के साथ लिखने की उपलब्धता के लिए मतदान पास हैं/अपने NSFileHandle की अंतर्निहित फ़ाइल वर्णनकर्ता पर हे उपलब्धता घटनाओं चाल हो सकती है, लेकिन मैं उन लोगों सुविधाओं का उपयोग कर से परिचित नहीं हूँ इस तरफ।

आप विकसित किया है आप मनमाने ढंग से सी कार्यक्रमों को समर्थन करने के लिए है, या यह एक विशेष डेमॉन या कुछ और है?

अगर यह अपने खुद के कार्यक्रम है, तो आप outputPipe पर प्रतिक्रिया के लिए अनुरोध के लिए देख सकते हैं, या बस inputPipe पर इनपुट विस्फोट आप पता लगा कि यह क्या है आप भेजना चाहते हैं, और सी कार्यक्रम में उपभोग इसके तैयार हो जाने जाने के रूप में;

http://www.cs.umd.edu/Library/TRs/CS-TR-4585/CS-TR-4585.pdf

: अगर यह किसी और की कोड है, तो आप एक लिंक-टाइम विधि का उपयोग कर परिशिष्ट A-4 के में वर्णित एक तरह (क्योंकि यह कोड आप संकलन कर रहे हैं) scanf और दोस्तों के हुक करने में सक्षम हो सकता

इसका कस्टम 0/आपके कस्टम I/O फ़ंक्शंस (जो आपके ऐप को कुछ सिगिल भेज सकता है, यह इंगित करता है कि उन्हें इनपुट की आवश्यकता है), लिंक प्रोग्राम में लिंक करें, पर्यावरण चर (DYLD_BIND_AT_LAUNCH=YES) सेट करें लॉन्च कार्य, और इसे चलाएं। एक बार जब आप उन हुक प्राप्त कर लेते हैं, तो आप अपने मेजबान कार्यक्रम के लिए जो भी सुविधा चाहते हैं उसे प्रदान कर सकते हैं।

+0

आपके उत्तर जो के लिए धन्यवाद। मैंने हाल ही में इस समस्या पर फिर से काम किया है और इसे काम कर लिया है (ठीक वही नहीं जो मैं चाहता हूं)। मैंने कमांड लाइन प्रोग्राम के लिए थोड़ा जीयूआई बनाया। जब मैं कमांड लाइन प्रोग्राम चलाता हूं तो मैं एक एनएसटीक्स्टव्यू में stdout प्रिंट करता हूं और उपयोगकर्ता एक NSTextField का उपयोग करके इनपुट प्रदान कर सकता है। समस्या यह है कि उपयोगकर्ता stdin को लिख सकता है भले ही प्रोग्राम को किसी भी इनपुट की आवश्यकता न हो। यही कारण है कि अगर मैं subprocess stdin से पढ़ने की कोशिश कर रहा हूं, तो मुझे एक अधिसूचना मिल सकती है। अपने प्रश्न का उत्तर देने के लिए: हाँ, मैं मनमानी सी कार्यक्रमों का समर्थन करना चाहता हूं। – Janek

+0

मैं चुनिंदा() और kqueue में गहराई से नजर डालेगा। दिलचस्प लग रहा है। कस्टम I/O फ़ंक्शन भी काम कर सकते हैं लेकिन मैं उनका उपयोग नहीं करना चाहूंगा। – Janek

+2

मुझे पूरी तरह से यकीन नहीं है कि, सामान्य मामले में, आप जान सकते हैं कि कोई प्रोग्राम इनपुट चाहता है या नहीं। ध्यान रखें कि ऐसे कार्यक्रम भी हैं जो गतिविधि के लिए इनपुट पाइप देखते हैं उदा। चुनें या kqueue (हैलो फिर से!)। एक साइड नोट के रूप में, यदि आप चाहते हैं कि आप इनपुट और आउटपुट दोनों के लिए एक एकल NSTextView का उपयोग कर सकें (कुछ छद्म के लिए [स्यूडोटीटी प्रोजेक्ट] (http://amath.colorado.edu/pub/mac/programs/) देखें लेकिन शायद अभी भी उपयोगी स्रोत कोड)। एफडब्ल्यूआईडब्लू, मेरा मानना ​​है कि यहां तक ​​कि 'टर्मिनल.एप' खुशी से इनपुट स्वीकार करेगा, चाहे यह चल रहा है कि प्रोग्राम अभी तक चाहता है, है ना? –

संबंधित मुद्दे