代码之家  ›  专栏  ›  技术社区  ›  Rob Keniger

处理加载到碳应用程序中的可可插件中的应用程序出口

  •  0
  • Rob Keniger  · 技术社区  · 14 年前

    我有一个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() 下面的函数,但是当应用程序终止时,我收到了我正在调用的警告 -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 回复  |  直到 14 年前
        1
  •  2
  •   Peter Hosey    14 年前

    很可能 NSApplicationLoad 设置NSApplication的第一个自动释放池,该池将位于自动释放池堆栈中您的池下方(因为它是第一个创建的)。在后台,它将排空这个池,并根据需要创建一个新的池;第一次这样做时, your pool goes away, since it was above Cocoa's pool in the stack .

    简单的解决方案是切断全局池,让NSApplication创建它。另一种选择是创造和排放 地方的 每个处理程序函数中的池,特别是当您实际上不需要插件中的应用程序工具包中的任何内容时。

        2
  •  1
  •   Nicholas Riley    14 年前

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

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