2012-07-19 25 views
8

Potrzebuję utworzyć obserwatora FSEvents dla folderu na Macu. Czuję się komfortowo z C++ i jest tam sposób, aby uzyskać powiadomienia FSEvents w C++, a nie Objective-C. Czy jest jakiś przykładowy kod na początek i wszystkie biblioteki, które muszę uwzględnić ..?FSEvents C++ Przykład

Jestem już na tej stronie. http://developer.apple.com/library/mac/#featuredarticles/FileSystemEvents/_index.html

Ale wydaje się, że jedynym celem C, mogę mieć CPP wersję nim

Odpowiedz

13

Tak, to jest możliwe w C. Należy szukać jądra kolejek.

Oto mała próbka do obejrzenia katalogu:

#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; 
} 

Szczegóły można znaleźć w rozdz. 16 (Kqueues i FSEvents) "Zaawansowanego programowania Mac OSX" autorstwa Marka Dalrymple. Dodatkowe informacje można znaleźć w dokumentacji * BSD dla kings.

Lub użyj tego API z FSEvents (jest to głównie oparte na C).

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

do tworzenia strumienia zdarzeń FSEvents z czystym C zwrotnym.

Następnie podłącz ten strumień zdarzeń do runloop pomocą

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

Tak, tutaj chyba powinien wykorzystywać linię Obj-C, aby uzyskać uchwyt RunLoop: uzyskać CFRunLoop z NSRunLoop za pomocą -getCFRunLoop

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

lub skorzystać z czystym C wezwanie

CFRunLoop* loopRef = CFRunLoopGetCurrent(); 

Zacznij imprezę strumieniowo z

Boolean FSEventStreamStart (FSEventStreamRef streamRef); 

zatrzymać strumień zdarzeń z

void FSEventStreamStop (FSEventStreamRef streamRef); 

A potem unschedule to z runloop z tym:

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

unieważnić strumień (czyszczenie):

void FSEventStreamInvalidate (FSEventStreamRef streamRef); 

Mam nadzieję, że dostaniesz tarted.

+0

W moich eksperymentach kqueue nie jest funkcjonalnym odpowiednikiem FSEvents. Dzięki za opisanie kawałka CFRunLoop! – berkus