Made event callbacks more rubust: keep an actual reference to the

python callback, and do RemoveEventHandler() upon deallocation.
This commit is contained in:
Just van Rossum 2001-12-14 23:16:04 +00:00
parent 9635f33e5b
commit 2c39115240
3 changed files with 113 additions and 30 deletions

View File

@ -41,13 +41,14 @@ class CarbonEvents_Scanner(Scanner_OSX):
listname = "functions" listname = "functions"
if arglist: if arglist:
t, n, m = arglist[0] t, n, m = arglist[0]
print "*********", t,
if t in RefObjectTypes and m == "InMode": if t in RefObjectTypes and m == "InMode":
print "method" if t == "EventHandlerRef":
classname = "CarbonEventsMethod" classname = "EventHandlerRefMethod"
else:
classname = "CarbonEventsMethod"
listname = t + "methods" listname = t + "methods"
else: #else:
print "not method" # print "not method"
return classname, listname return classname, listname
def writeinitialdefs(self): def writeinitialdefs(self):
@ -82,6 +83,7 @@ class CarbonEvents_Scanner(Scanner_OSX):
# Wrote by hand # Wrote by hand
"InstallEventHandler", "InstallEventHandler",
"RemoveEventHandler",
"RunApplicationEventLoop", "RunApplicationEventLoop",
# Write by hand? # Write by hand?

View File

@ -11,6 +11,7 @@ for typ in RefObjectTypes:
execstr = "%(name)s = OpaqueByValueType('%(name)s')" % {"name": typ} execstr = "%(name)s = OpaqueByValueType('%(name)s')" % {"name": typ}
exec execstr exec execstr
if 0: if 0:
# these types will have no methods and will merely be opaque blobs # these types will have no methods and will merely be opaque blobs
# should write getattr and setattr for them? # should write getattr and setattr for them?
@ -53,6 +54,14 @@ EventHandlerProcPtr = FakeType("(EventHandlerProcPtr)0")
CarbonEventsFunction = OSErrFunctionGenerator CarbonEventsFunction = OSErrFunctionGenerator
CarbonEventsMethod = OSErrMethodGenerator 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""" includestuff = r"""
#ifdef WITHOUT_FRAMEWORKS #ifdef WITHOUT_FRAMEWORKS
#include <CarbonEvents.h> #include <CarbonEvents.h>
@ -188,15 +197,31 @@ myEventHandlerUPP = NewEventHandlerUPP(myEventHandler);
""" """
module = MacModule('_CarbonEvt', 'CarbonEvents', includestuff, finalstuff, initstuff) 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: for typ in RefObjectTypes:
execstr = typ + 'object = GlobalObjectDefinition(typ)' if typ == 'EventHandlerRef':
exec execstr EventHandlerRefobject = EventHandlerRefObjectDefinition('EventHandlerRef')
else:
execstr = typ + 'object = GlobalObjectDefinition(typ)'
exec execstr
module.addobject(eval(typ + 'object')) module.addobject(eval(typ + 'object'))
functions = [] functions = []
for typ in RefObjectTypes: ## go thru all ObjectTypes as defined in CarbonEventsscan.py for typ in RefObjectTypes: ## go thru all ObjectTypes as defined in CarbonEventsscan.py
# initialize the lists for carbongen to fill # 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') execfile('CarbonEventsgen.py')
for f in functions: module.add(f) # add all the functions carboneventsgen put in the list 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 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 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 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 = """ installeventhandler = """
EventTypeSpec inSpec; EventTypeSpec inSpec;
PyObject *callback; 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); _err = InstallEventHandler(_self->ob_itself, myEventHandlerUPP, 1, &inSpec, (void *)callback, &outRef);
if (_err != noErr) return PyMac_Error(_err); 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 = 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) EventTargetRefobject.add(f)
runappeventloop = """ runappeventloop = """

View File

@ -799,6 +799,7 @@ PyTypeObject EventHandlerRef_Type;
typedef struct EventHandlerRefObject { typedef struct EventHandlerRefObject {
PyObject_HEAD PyObject_HEAD
EventHandlerRef ob_itself; EventHandlerRef ob_itself;
PyObject *ob_callback;
} EventHandlerRefObject; } EventHandlerRefObject;
PyObject *EventHandlerRef_New(EventHandlerRef itself) PyObject *EventHandlerRef_New(EventHandlerRef itself)
@ -807,6 +808,7 @@ PyObject *EventHandlerRef_New(EventHandlerRef itself)
it = PyObject_NEW(EventHandlerRefObject, &EventHandlerRef_Type); it = PyObject_NEW(EventHandlerRefObject, &EventHandlerRef_Type);
if (it == NULL) return NULL; if (it == NULL) return NULL;
it->ob_itself = itself; it->ob_itself = itself;
it->ob_callback = NULL;
return (PyObject *)it; return (PyObject *)it;
} }
int EventHandlerRef_Convert(PyObject *v, EventHandlerRef *p_itself) 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) 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); 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) static PyObject *EventHandlerRef_AddEventTypesToHandler(EventHandlerRefObject *_self, PyObject *_args)
{ {
PyObject *_res = NULL; PyObject *_res = NULL;
OSStatus _err; OSStatus _err;
UInt32 inNumTypes; UInt32 inNumTypes;
EventTypeSpec inList; EventTypeSpec inList;
if (_self->ob_itself == NULL) {
PyErr_SetString(CarbonEvents_Error, "Handler has been removed");
return NULL;
}
if (!PyArg_ParseTuple(_args, "lO&", if (!PyArg_ParseTuple(_args, "lO&",
&inNumTypes, &inNumTypes,
EventTypeSpec_Convert, &inList)) EventTypeSpec_Convert, &inList))
@ -864,6 +860,10 @@ static PyObject *EventHandlerRef_RemoveEventTypesFromHandler(EventHandlerRefObje
OSStatus _err; OSStatus _err;
UInt32 inNumTypes; UInt32 inNumTypes;
EventTypeSpec inList; EventTypeSpec inList;
if (_self->ob_itself == NULL) {
PyErr_SetString(CarbonEvents_Error, "Handler has been removed");
return NULL;
}
if (!PyArg_ParseTuple(_args, "lO&", if (!PyArg_ParseTuple(_args, "lO&",
&inNumTypes, &inNumTypes,
EventTypeSpec_Convert, &inList)) EventTypeSpec_Convert, &inList))
@ -877,13 +877,34 @@ static PyObject *EventHandlerRef_RemoveEventTypesFromHandler(EventHandlerRefObje
return _res; 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[] = { static PyMethodDef EventHandlerRef_methods[] = {
{"RemoveEventHandler", (PyCFunction)EventHandlerRef_RemoveEventHandler, 1,
"() -> None"},
{"AddEventTypesToHandler", (PyCFunction)EventHandlerRef_AddEventTypesToHandler, 1, {"AddEventTypesToHandler", (PyCFunction)EventHandlerRef_AddEventTypesToHandler, 1,
"(UInt32 inNumTypes, EventTypeSpec inList) -> None"}, "(UInt32 inNumTypes, EventTypeSpec inList) -> None"},
{"RemoveEventTypesFromHandler", (PyCFunction)EventHandlerRef_RemoveEventTypesFromHandler, 1, {"RemoveEventTypesFromHandler", (PyCFunction)EventHandlerRef_RemoveEventTypesFromHandler, 1,
"(UInt32 inNumTypes, EventTypeSpec inList) -> None"}, "(UInt32 inNumTypes, EventTypeSpec inList) -> None"},
{"RemoveEventHandler", (PyCFunction)EventHandlerRef_RemoveEventHandler, 1,
"() -> None"},
{NULL, NULL, 0} {NULL, NULL, 0}
}; };
@ -1083,14 +1104,19 @@ static PyObject *EventTargetRef_InstallEventHandler(EventTargetRefObject *_self,
_err = InstallEventHandler(_self->ob_itself, myEventHandlerUPP, 1, &inSpec, (void *)callback, &outRef); _err = InstallEventHandler(_self->ob_itself, myEventHandlerUPP, 1, &inSpec, (void *)callback, &outRef);
if (_err != noErr) return PyMac_Error(_err); 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[] = { static PyMethodDef EventTargetRef_methods[] = {
{"InstallStandardEventHandler", (PyCFunction)EventTargetRef_InstallStandardEventHandler, 1, {"InstallStandardEventHandler", (PyCFunction)EventTargetRef_InstallStandardEventHandler, 1,
"() -> None"}, "() -> None"},
{"InstallEventHandler", (PyCFunction)EventTargetRef_InstallEventHandler, 1, {"InstallEventHandler", (PyCFunction)EventTargetRef_InstallEventHandler, 1,
"(EventTargetRef inTarget, EventTypeSpec inSpec, Method callback) -> (EventHandlerRef outRef)"}, "(EventTypeSpec inSpec, Method callback) -> (EventHandlerRef outRef)"},
{NULL, NULL, 0} {NULL, NULL, 0}
}; };