]> granicus.if.org Git - python/commitdiff
Made event callbacks more rubust: keep an actual reference to the
authorJust van Rossum <just@letterror.com>
Fri, 14 Dec 2001 23:16:04 +0000 (23:16 +0000)
committerJust van Rossum <just@letterror.com>
Fri, 14 Dec 2001 23:16:04 +0000 (23:16 +0000)
python callback, and do RemoveEventHandler() upon deallocation.

Mac/Modules/carbonevt/CarbonEvtscan.py
Mac/Modules/carbonevt/CarbonEvtsupport.py
Mac/Modules/carbonevt/_CarbonEvtmodule.c

index 856f9b10c397613f2344efbbd7e24997b46ddf8f..e93baf3d03f630e28a5310fbfdf14dd65f26e762 100644 (file)
@@ -41,13 +41,14 @@ class CarbonEvents_Scanner(Scanner_OSX):
                listname = "functions"
                if arglist:
                        t, n, m = arglist[0]
-                       print "*********", t,
                        if t in RefObjectTypes and m == "InMode":
-                               print "method"
-                               classname = "CarbonEventsMethod"
+                               if t == "EventHandlerRef":
+                                       classname = "EventHandlerRefMethod"
+                               else:
+                                       classname = "CarbonEventsMethod"
                                listname = t + "methods"
-                       else:
-                               print "not method"
+                       #else:
+                       #       print "not method"
                return classname, listname
 
        def writeinitialdefs(self):
@@ -82,6 +83,7 @@ class CarbonEvents_Scanner(Scanner_OSX):
 
                        # Wrote by hand
                        "InstallEventHandler",
+                       "RemoveEventHandler",
                        "RunApplicationEventLoop",
                                                
                        # Write by hand?
index a43d47c5b1909e784e5f75cd66c30e2aea712558..ef862ee05617b36dd3feda59209b6224219a38cb 100644 (file)
@@ -11,6 +11,7 @@ for typ in RefObjectTypes:
        execstr = "%(name)s = OpaqueByValueType('%(name)s')" % {"name": typ}
        exec execstr
 
+
 if 0:
        # these types will have no methods and will merely be opaque blobs
        # should write getattr and setattr for them?
@@ -53,6 +54,14 @@ EventHandlerProcPtr = FakeType("(EventHandlerProcPtr)0")
 CarbonEventsFunction = OSErrFunctionGenerator
 CarbonEventsMethod = OSErrMethodGenerator
 
+class EventHandlerRefMethod(OSErrMethodGenerator):
+       def precheck(self):
+               OutLbrace('if (_self->ob_itself == NULL)')
+               Output('PyErr_SetString(CarbonEvents_Error, "Handler has been removed");')
+               Output('return NULL;')
+               OutRbrace()
+
+
 includestuff = r"""
 #ifdef WITHOUT_FRAMEWORKS
 #include <CarbonEvents.h>
@@ -188,15 +197,31 @@ myEventHandlerUPP = NewEventHandlerUPP(myEventHandler);
 """
 module = MacModule('_CarbonEvt', 'CarbonEvents', includestuff, finalstuff, initstuff)
 
-#class CFReleaserObj(GlobalObjectDefinition):
-#      def outputFreeIt(self, name):
-#              Output("CFRelease(%s);" % name)
+
+
+
+class EventHandlerRefObjectDefinition(GlobalObjectDefinition):
+       def outputStructMembers(self):
+               Output("%s ob_itself;", self.itselftype)
+               Output("PyObject *ob_callback;")
+       def outputInitStructMembers(self):
+               Output("it->ob_itself = %sitself;", self.argref)
+               Output("it->ob_callback = NULL;")
+       def outputFreeIt(self, name):
+               OutLbrace("if (self->ob_itself != NULL)")
+               Output("RemoveEventHandler(self->ob_itself);")
+               Output("Py_DECREF(self->ob_callback);")
+               OutRbrace()
 
 for typ in RefObjectTypes:
-       execstr = typ + 'object = GlobalObjectDefinition(typ)'
-       exec execstr
+       if typ == 'EventHandlerRef':
+               EventHandlerRefobject = EventHandlerRefObjectDefinition('EventHandlerRef')
+       else:
+               execstr = typ + 'object = GlobalObjectDefinition(typ)'
+               exec execstr
        module.addobject(eval(typ + 'object'))
 
+
 functions = []
 for typ in RefObjectTypes: ## go thru all ObjectTypes as defined in CarbonEventsscan.py
        # initialize the lists for carbongen to fill
@@ -205,6 +230,8 @@ for typ in RefObjectTypes: ## go thru all ObjectTypes as defined in CarbonEvents
 
 execfile('CarbonEventsgen.py')
 
+
+
 for f in functions: module.add(f)      # add all the functions carboneventsgen put in the list
 
 for typ in RefObjectTypes:                              ## go thru all ObjectTypes as defined in CarbonEventsscan.py
@@ -212,6 +239,29 @@ for typ in RefObjectTypes:                          ## go thru all ObjectTypes as defined in CarbonEv
        obj = eval(typ + 'object')                ## get a reference to the object
        for m in methods: obj.add(m)    ## add each method in the list to the object
 
+
+removeeventhandler = """
+OSStatus _err;
+if (_self->ob_itself == NULL) {
+       PyErr_SetString(CarbonEvents_Error, "Handler has been removed");
+       return NULL;
+}
+if (!PyArg_ParseTuple(_args, ""))
+       return NULL;
+_err = RemoveEventHandler(_self->ob_itself);
+if (_err != noErr) return PyMac_Error(_err);
+_self->ob_itself = NULL;
+Py_DECREF(_self->ob_callback);
+_self->ob_callback = NULL;
+Py_INCREF(Py_None);
+_res = Py_None;
+return _res;"""
+
+f = ManualGenerator("RemoveEventHandler", removeeventhandler);
+f.docstring = lambda: "() -> None"
+EventHandlerRefobject.add(f)
+
+
 installeventhandler = """
 EventTypeSpec inSpec;
 PyObject *callback;
@@ -224,10 +274,15 @@ if (!PyArg_ParseTuple(_args, "O&O", EventTypeSpec_Convert, &inSpec, &callback))
 _err = InstallEventHandler(_self->ob_itself, myEventHandlerUPP, 1, &inSpec, (void *)callback, &outRef);
 if (_err != noErr) return PyMac_Error(_err);
 
-return Py_BuildValue("O&", EventHandlerRef_New, outRef);"""
+_res = EventHandlerRef_New(outRef);
+if (_res != NULL) {
+       ((EventHandlerRefObject*)_res)->ob_callback = callback;
+       Py_INCREF(callback);
+}
+return _res;"""
 
 f = ManualGenerator("InstallEventHandler", installeventhandler);
-f.docstring = lambda: "(EventTargetRef inTarget, EventTypeSpec inSpec, Method callback) -> (EventHandlerRef outRef)"
+f.docstring = lambda: "(EventTypeSpec inSpec, Method callback) -> (EventHandlerRef outRef)"
 EventTargetRefobject.add(f)
 
 runappeventloop = """
index 0aefcc6d17166de45eeba9e96fd9635a38acdce6..f9f38866134d03e06c96456d94fe416390d1bdcb 100755 (executable)
@@ -799,6 +799,7 @@ PyTypeObject EventHandlerRef_Type;
 typedef struct EventHandlerRefObject {
        PyObject_HEAD
        EventHandlerRef ob_itself;
+       PyObject *ob_callback;
 } EventHandlerRefObject;
 
 PyObject *EventHandlerRef_New(EventHandlerRef itself)
@@ -807,6 +808,7 @@ PyObject *EventHandlerRef_New(EventHandlerRef itself)
        it = PyObject_NEW(EventHandlerRefObject, &EventHandlerRef_Type);
        if (it == NULL) return NULL;
        it->ob_itself = itself;
+       it->ob_callback = NULL;
        return (PyObject *)it;
 }
 int EventHandlerRef_Convert(PyObject *v, EventHandlerRef *p_itself)
@@ -822,29 +824,23 @@ int EventHandlerRef_Convert(PyObject *v, EventHandlerRef *p_itself)
 
 static void EventHandlerRef_dealloc(EventHandlerRefObject *self)
 {
-       /* Cleanup of self->ob_itself goes here */
+       if (self->ob_itself != NULL) {
+               RemoveEventHandler(self->ob_itself);
+               Py_DECREF(self->ob_callback);
+       }
        PyMem_DEL(self);
 }
 
-static PyObject *EventHandlerRef_RemoveEventHandler(EventHandlerRefObject *_self, PyObject *_args)
-{
-       PyObject *_res = NULL;
-       OSStatus _err;
-       if (!PyArg_ParseTuple(_args, ""))
-               return NULL;
-       _err = RemoveEventHandler(_self->ob_itself);
-       if (_err != noErr) return PyMac_Error(_err);
-       Py_INCREF(Py_None);
-       _res = Py_None;
-       return _res;
-}
-
 static PyObject *EventHandlerRef_AddEventTypesToHandler(EventHandlerRefObject *_self, PyObject *_args)
 {
        PyObject *_res = NULL;
        OSStatus _err;
        UInt32 inNumTypes;
        EventTypeSpec inList;
+       if (_self->ob_itself == NULL) {
+               PyErr_SetString(CarbonEvents_Error, "Handler has been removed");
+               return NULL;
+       }
        if (!PyArg_ParseTuple(_args, "lO&",
                              &inNumTypes,
                              EventTypeSpec_Convert, &inList))
@@ -864,6 +860,10 @@ static PyObject *EventHandlerRef_RemoveEventTypesFromHandler(EventHandlerRefObje
        OSStatus _err;
        UInt32 inNumTypes;
        EventTypeSpec inList;
+       if (_self->ob_itself == NULL) {
+               PyErr_SetString(CarbonEvents_Error, "Handler has been removed");
+               return NULL;
+       }
        if (!PyArg_ParseTuple(_args, "lO&",
                              &inNumTypes,
                              EventTypeSpec_Convert, &inList))
@@ -877,13 +877,34 @@ static PyObject *EventHandlerRef_RemoveEventTypesFromHandler(EventHandlerRefObje
        return _res;
 }
 
+static PyObject *EventHandlerRef_RemoveEventHandler(EventHandlerRefObject *_self, PyObject *_args)
+{
+       PyObject *_res = NULL;
+
+       OSStatus _err;
+       if (_self->ob_itself == NULL) {
+               PyErr_SetString(CarbonEvents_Error, "Handler has been removed");
+               return NULL;
+       }
+       if (!PyArg_ParseTuple(_args, ""))
+               return NULL;
+       _err = RemoveEventHandler(_self->ob_itself);
+       if (_err != noErr) return PyMac_Error(_err);
+       _self->ob_itself = NULL;
+       Py_DECREF(_self->ob_callback);
+       _self->ob_callback = NULL;
+       Py_INCREF(Py_None);
+       _res = Py_None;
+       return _res;
+}
+
 static PyMethodDef EventHandlerRef_methods[] = {
-       {"RemoveEventHandler", (PyCFunction)EventHandlerRef_RemoveEventHandler, 1,
-        "() -> None"},
        {"AddEventTypesToHandler", (PyCFunction)EventHandlerRef_AddEventTypesToHandler, 1,
         "(UInt32 inNumTypes, EventTypeSpec inList) -> None"},
        {"RemoveEventTypesFromHandler", (PyCFunction)EventHandlerRef_RemoveEventTypesFromHandler, 1,
         "(UInt32 inNumTypes, EventTypeSpec inList) -> None"},
+       {"RemoveEventHandler", (PyCFunction)EventHandlerRef_RemoveEventHandler, 1,
+        "() -> None"},
        {NULL, NULL, 0}
 };
 
@@ -1083,14 +1104,19 @@ static PyObject *EventTargetRef_InstallEventHandler(EventTargetRefObject *_self,
        _err = InstallEventHandler(_self->ob_itself, myEventHandlerUPP, 1, &inSpec, (void *)callback, &outRef);
        if (_err != noErr) return PyMac_Error(_err);
 
-       return Py_BuildValue("O&", EventHandlerRef_New, outRef);
+       _res = EventHandlerRef_New(outRef);
+       if (_res != NULL) {
+               ((EventHandlerRefObject*)_res)->ob_callback = callback;
+               Py_INCREF(callback);
+       }
+       return _res;
 }
 
 static PyMethodDef EventTargetRef_methods[] = {
        {"InstallStandardEventHandler", (PyCFunction)EventTargetRef_InstallStandardEventHandler, 1,
         "() -> None"},
        {"InstallEventHandler", (PyCFunction)EventTargetRef_InstallEventHandler, 1,
-        "(EventTargetRef inTarget, EventTypeSpec inSpec, Method callback) -> (EventHandlerRef outRef)"},
+        "(EventTypeSpec inSpec, Method callback) -> (EventHandlerRef outRef)"},
        {NULL, NULL, 0}
 };