Made event callbacks more rubust: keep an actual reference to the
python callback, and do RemoveEventHandler() upon deallocation.
This commit is contained in:
parent
9635f33e5b
commit
2c39115240
|
@ -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?
|
||||||
|
|
|
@ -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 = """
|
||||||
|
|
|
@ -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}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue