【问题标题】:FSEvents C++ ExampleFSEvents C++ 示例
【发布时间】:2012-07-19 08:10:37
【问题描述】:

我需要为 Mac 中的文件夹创建 FSEvents 观察程序。我对 C++ 很满意,有没有办法在 C++ 代码而不是 Objective-C 中获取 FSEvents 通知。是否有一些示例代码可以开始以及我需要包含的任何库..?

我已经在这个页面上了。 http://developer.apple.com/library/mac/#featuredarticles/FileSystemEvents/_index.html

但是好像只有Objective C,我可以有它的CPP版本吗

【问题讨论】:

    标签: c++ c macos fsevents


    【解决方案1】:

    是的,在 C 中是可能的。你应该寻找内核队列。

    这里有一个小示例来观看目录:

    #include <errno.h>       // for errno
    #include <fcntl.h>       // for O_RDONLY
    #include <stdio.h>       // for fprintf()
    #include <stdlib.h>      // for EXIT_SUCCESS
    #include <string.h>      // for strerror()
    #include <sys/event.h>   // for kqueue() etc.
    #include <unistd.h>      // for close()
    
    int main (int argc, const char *argv[])
    {
       int kq = kqueue ();
       // dir name is in argv[1], NO checks for errors here
       int dirfd = open (argv[1], O_RDONLY);
    
       struct kevent direvent;
        EV_SET (&direvent, dirfd, EVFILT_VNODE, EV_ADD | EV_CLEAR | EV_ENABLE,
                NOTE_WRITE, 0, (void *)dirname);
    
       kevent(kq, &direvent, 1, NULL, 0, NULL);
    
       // Register interest in SIGINT with the queue.  The user data
       // is NULL, which is how we'll differentiate between
       // a directory-modification event and a SIGINT-received event.
       struct kevent sigevent;
       EV_SET (&sigevent, SIGINT, EVFILT_SIGNAL, EV_ADD | EV_ENABLE, 0, 0, NULL);
       // kqueue event handling happens after the legacy API, so make
       // sure it doesn eat the signal before the kqueue can see it.
       signal (SIGINT, SIG_IGN);
    
       // Register the signal event.
       kevent(kq, &sigevent, 1, NULL, 0, NULL);
    
       while (1) {
           // camp on kevent() until something interesting happens
           struct kevent change;
           if (kevent(kq, NULL, 0, &change, 1, NULL) == -1) { exit(1); }
           // The signal event has NULL in the user data.  Check for that first.
           if (change.udata == NULL) {
               break;
           } else {
            // udata is non-null, so it's the name of the directory
            printf ("%s\n", (char*)change.udata);
           }
       }
       close (kq);
       return 0;
    }
    

    详细信息可以在 ch 中找到。 Mark Dalrymple 的“高级 Mac OSX 编程”的 16(kqueues 和 FSEvents)。附加信息可以在 kqueue 的 *BSD 文档中找到。

    或者使用 FSEvents 的这个 API(它主要是基于 C 的)。

    FSEventStreamRef FSEventStreamCreate (CFAllocatorRef allocator,
                                      FSEventStreamCallback callback,
                                      FSEventStreamContext *context,
                                      CFArrayRef pathsToWatch,
                                      FSEventStreamEventId sinceWhen,
                                      CFTimeInterval latency,
                                      FSEventStreamCreateFlags flags);
    

    使用纯 C 回调创建 FSEvents 事件流。

    然后使用

    将此事件流附加到您的运行循环
    void FSEventStreamScheduleWithRunLoop (FSEventStreamRef streamRef,
                                       CFRunLoopRef runLoop,
                                       CFStringRef runLoopMode);
    

    是的,这里你可能应该使用一行 Obj-C 来获取 RunLoop 句柄:使用 -getCFRunLoop 从 NSRunLoop 获取 CFRunLoop

    CFRunLoop* loopRef = [[NSRunLoop currentRunLoop] getCFRunLoop];
    

    或使用纯 C 调用

    CFRunLoop* loopRef =  CFRunLoopGetCurrent();
    

    启动事件流

    Boolean FSEventStreamStart (FSEventStreamRef streamRef);
    

    停止事件流

    void FSEventStreamStop (FSEventStreamRef streamRef);
    

    然后使用以下命令从运行循环中取消调度它:

    void FSEventStreamUnscheduleFromRunLoop (FSEventStreamRef streamRef,
                                         CFRunLoopRef runLoop,
                                         CFStringRef runLoopMode);
    

    使流无效(清理):

    void FSEventStreamInvalidate (FSEventStreamRef streamRef);
    

    希望这能让你开始。

    【讨论】:

    • 在我的实验中,kqueue 在功能上并不等同于 FSEvents。感谢您概述 CFRunLoop 位!
    • 在您的第一个小样本中,似乎没有定义“目录名”...?
    • @Sugar:你说得对,const char* dirname = "some_dir_name" 肯定不见了。其实也可以是const char* dirname = argv[1];
    • @ViktorLatypov 谢谢,你的样本真的很有帮助! :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-03-12
    • 2010-12-18
    • 2012-09-12
    • 2010-11-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多