【问题标题】:Objective C : How to keep listening to incoming data on stdin?目标 C:如何继续收听标准输入上的传入数据?
【发布时间】:2021-11-08 14:32:50
【问题描述】:

我正在尝试使用 native messaging 从浏览器扩展调用用 Objective C 编写的 MacOS 应用程序。

到目前为止,我已经想出了处理使用chrome.runtime.sendNativeMessage 发出的请求的代码。

int main(int argc, char * argv[]) {
  @autoreleasepool {
    NSFileHandle *stdIn = [NSFileHandle fileHandleWithStandardInput];
    NSError * stdinError = nil;
    NSData * rawReqLen = [stdIn readDataUpToLength:4 error:&stdinError];
    if(rawReqLen == nil || stdinError != nil) return 1;
    NSUInteger reqLen;
    [rawReqLen getBytes:&reqLen length:4];

    NSData * req = [stdIn readDataUpToLength:reqLen error:&stdinError];
    if(stdinError != nil) return 1;

    handleRequest(req); // this does something depending on the received request

    return 0;
  }
}

这是有效的。

我需要帮助弄清楚如何使用chrome.connectNative 来保持连接打开。具体来说,我的问题是让 MacOS 应用程序继续侦听传入的消息,直到通过从浏览器扩展程序调用 port.disconnect 关闭端口。

我试过这段代码不起作用。

int main(int argc, char * argv[]) {
  @autoreleasepool {
    NSFileHandle *stdIn = [NSFileHandle fileHandleWithStandardInput];
  
    [[NSNotificationCenter defaultCenter] addObserverForName:NSFileHandleDataAvailableNotification
                                                          object:stdIn
                                                         queue:[NSOperationQueue mainQueue]
                                                      usingBlock:^(NSNotification *note) {
      NSError * stdinError = nil;
      NSData * rawReqLen = [stdIn readDataUpToLength:4 error:&stdinError];
      if(rawReqLen == nil || stdinError != nil) exit(1);
      NSUInteger reqLen;
      [rawReqLen getBytes:&reqLen length:4];

      NSData * req = [stdIn readDataUpToLength:reqLen error:&stdinError];
      if(stdinError != nil) exit(1);

      handleRequest(req);
    }];
    [stdIn waitForDataInBackgroundAndNotify];
  }
}

有人知道如何做到这一点吗?

【问题讨论】:

    标签: objective-c stdin chrome-native-messaging


    【解决方案1】:

    解决办法是:

    int main(int argc, char * argv[]) {
      @autoreleasepool {
        NSFileHandle *stdIn = [NSFileHandle fileHandleWithStandardInput];
      
        [[NSNotificationCenter defaultCenter] addObserverForName:NSFileHandleDataAvailableNotification
                                                              object:stdIn
                                                             queue:[NSOperationQueue mainQueue]
                                                          usingBlock:^(NSNotification *note) {
          NSError * stdinError = nil;
          NSData * rawReqLen = [stdIn readDataUpToLength:4 error:&stdinError];
          if(rawReqLen == nil || stdinError != nil) exit(1);
          uint32_t reqLen;
          [rawReqLen getBytes:&reqLen length:4];
          reqLen = OSSwapLittleToHostInt32(reqLen);
    
          NSData * req = [stdIn readDataUpToLength:reqLen error:&stdinError];
          if(stdinError != nil) exit(1);
    
          handleRequest(req);
          [stdIn waitForDataInBackgroundAndNotify];
        }];
        [stdIn waitForDataInBackgroundAndNotify];
      }
    
      NSRunLoop *loop = [NSRunLoop currentRunLoop];
      [loop acceptInputForMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
      [loop run];
      return 0;
    }
    
    

    如果您想保持端口打开,也可以将调用 exit(1) 替换为对 [stdIn waitForDataInBackgroundAndNotify]; 的新调用。

    这可以很好地处理传入的请求,但会中断响应:写入标准输出不再起作用,我可能需要停止每个响应的运行循环并在完成后重新启动它。 (尚未测试)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-25
      • 1970-01-01
      • 1970-01-01
      • 2021-01-06
      • 1970-01-01
      • 2021-12-30
      相关资源
      最近更新 更多