2012-07-19 51 views
8

Tôi cần tạo trình theo dõi FSEvents cho một Thư mục trong Mac. Tôi cảm thấy thoải mái với C++ và có cách nào để nhận thông báo FSEvents trong mã C++, thay vì Objective-C. Có một số ví dụ mã để bắt đầu với và bất kỳ thư viện tôi cần phải bao gồm ..?FSEvents Ví dụ C++

Tôi đã ở trên trang này. http://developer.apple.com/library/mac/#featuredarticles/FileSystemEvents/_index.html

Nhưng có vẻ là chỉ Objective C, tôi có thể có CPP phiên bản của nó

Trả lời

13

Có, có thể trong C. Bạn nên tìm kiếm Kernel Queues.

Dưới đây là một mẫu nhỏ để xem các thư mụ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; 
} 

Các chi tiết có thể được tìm thấy trong ch. 16 (kqueues và FSEvents) của "Lập trình Mac OSX nâng cao" của Mark Dalrymple. Thông tin bổ sung có thể được tìm thấy trong tài liệu * BSD cho kqueues.

Hoặc sử dụng API này từ FSEvents (chủ yếu dựa trên C).

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

để tạo luồng sự kiện FSEvents bằng gọi lại C thuần túy.

Sau đó đính kèm dòng sự kiện này để runloop của bạn bằng cách sử dụng

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

Vâng, đây có lẽ bạn nên sử dụng một dòng obj-C để có được xử lý runloop: lấy CFRunLoop từ một NSRunLoop bằng cách sử dụng -getCFRunLoop

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

hoặc sử dụng C gọi tinh khiết

CFRunLoop* loopRef = CFRunLoopGetCurrent(); 

Bắt đầu sự kiện dòng với

Boolean FSEventStreamStart (FSEventStreamRef streamRef); 

Dừng luồng sự kiện với

void FSEventStreamStop (FSEventStreamRef streamRef); 

Và sau đó unschedule nó từ runloop với điều này:

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

Vô hiệu hóa luồng (dọn dẹp):

void FSEventStreamInvalidate (FSEventStreamRef streamRef); 

Hy vọng điều này sẽ giúp bạn tarted.

+0

Trong thử nghiệm của tôi, kqueue không có chức năng tương đương với FSEvents. Cảm ơn bạn đã phác thảo bit CFRunLoop! – berkus