处理加载到Carbon应用程序中的Cocoa插件中的应用程序出口

时间:2010-02-10 07:30:27

标签: cocoa macos events plugins macos-carbon

我有一个Cocoa插件,它被加载到现有的Carbon应用程序中。

首次加载插件时,Carbon应用程序调用初始化函数Plugin_Init(),并在该函数中设置环境,如下所示:

//this is the global autorelease pool
static NSAutoreleasePool* globalPool = nil;

void Plugin_Init()
{
    NSApplicationLoad(); //loads the Cocoa event loop etc
    //create an autorelease pool
    globalPool=[[NSAutoreleasePool alloc] init];

    //callback functions are registered here
    Plugin_defineFunction("doSomething",doSomething,0);
}

但是,Carbon应用程序在应用程序即将终止时不会发送任何通知。

是否真的有必要清理我在应用程序终止时创建的“全局”自动释放池?

我尝试通过添加对下面registerForApplicationQuitNotification()函数的调用来注册Carbon app quit事件,但是当应用程序终止时,我收到警告,我在无效的自动释放池上调用了-release。我是如何处理碳事件的?

//handles the Carbon application quit notification
static pascal OSStatus handleApplicationQuitEvent(EventHandlerCallRef nextHandler, EventRef evt, void *ud)
{
    OSStatus err = noErr;
    UInt32 evtkind;
    evtkind = GetEventKind( evt );
    if ( evtkind == kEventAppQuit ) 
    {
        //release the global autorelease pool
        [globalPool release];
    }
    // call the rest of the handlers
    err = CallNextEventHandler( nextHandler, evt);
    return err;
}

//registers for the Carbon application quit notification
void registerForApplicationQuitNotification()
{
    // install an event handler to tear down some globals on Quit
    static EventHandlerUPP app = NULL;
    EventTypeSpec list[] = {
        {kEventClassApplication, kEventAppQuit},
    };
    app = NewEventHandlerUPP( handleApplicationQuitEvent );
    if (!app)
        return;
    InstallApplicationEventHandler(app, GetEventTypeCount(list), list, NULL, NULL);
}

2 个答案:

答案 0 :(得分:2)

很可能NSApplicationLoad设置了NSApplication的第一个自动释放池,它将在自动释放池堆栈中低于你自己(因为它是首先创建的)。在后台,它将耗尽这个池并根据需要创建一个新池;这是第一次发生your pool goes away, since it was above Cocoa's pool in the stack

简单的解决方案是删除全局池,让NSApplication创建它。另一种方法是在每个处理函数中创建和排空本地池,特别是如果您实际上不需要插件中的Application Kit中的任何内容。

答案 1 :(得分:1)

如果自动释放池是您需要进行的唯一清理,那么不,您不需要注册退出通知。您创建的任何池仍然在应用程序的地址空间内,当进程终止时,操作系统将释放该空间。

此外,自动释放池通常是每个线程创建的。如果在不同的线程上调用回调,则可能需要为每个线程创建一个池。请注意,Cocoa也需要被告知它在多线程环境中运行;请参阅NSAutoreleasePool reference

的“主题”部分