From add03b62fd6ec982785432b64b783441f9fcb879 Mon Sep 17 00:00:00 2001 From: Jack Jansen Date: Wed, 8 Mar 2000 16:58:15 +0000 Subject: Handles were never disposed. Added an AutoDispose(onoff) method to control this. Also added a Handle() function which is like Resource() but has auto-dispose on by default. --- Mac/Modules/res/Resmodule.c | 70 ++++++++++++++++++++++++++++++++++++++++--- Mac/Modules/res/resedit.py | 56 ++++++++++++++++++++++++++++++++-- Mac/Modules/res/ressupport.py | 27 +++++++++++++++-- 3 files changed, 143 insertions(+), 10 deletions(-) diff --git a/Mac/Modules/res/Resmodule.c b/Mac/Modules/res/Resmodule.c index 4f0f3c8..d0495e5 100644 --- a/Mac/Modules/res/Resmodule.c +++ b/Mac/Modules/res/Resmodule.c @@ -47,6 +47,13 @@ extern PyObject *WinObj_WhichWindow(WindowPtr); #define resNotFound -192 /* Can't include because of Python's "errors.h" */ +/* Function to dispose a resource, with a "normal" calling sequence */ +static void +PyMac_AutoDisposeHandle(Handle h) +{ + DisposeHandle(h); +} + static PyObject *Res_Error; /* ---------------------- Object type Resource ---------------------- */ @@ -58,6 +65,7 @@ PyTypeObject Resource_Type; typedef struct ResourceObject { PyObject_HEAD Handle ob_itself; + void (*ob_freeit)(Handle ptr); } ResourceObject; PyObject *ResObj_New(itself) @@ -68,6 +76,7 @@ PyObject *ResObj_New(itself) it = PyObject_NEW(ResourceObject, &Resource_Type); if (it == NULL) return NULL; it->ob_itself = itself; + it->ob_freeit = NULL; return (PyObject *)it; } ResObj_Convert(v, p_itself) @@ -97,7 +106,11 @@ ResObj_Convert(v, p_itself) static void ResObj_dealloc(self) ResourceObject *self; { - /* Cleanup of self->ob_itself goes here */ + if (self->ob_freeit && self->ob_itself) + { + self->ob_freeit(self->ob_itself); + } + self->ob_itself = NULL; PyMem_DEL(self); } @@ -462,6 +475,25 @@ static PyObject *ResObj_LoadResource(_self, _args) return _res; } +static PyObject *ResObj_AutoDispose(_self, _args) + ResourceObject *_self; + PyObject *_args; +{ + PyObject *_res = NULL; + + int onoff, old = 0; + if (!PyArg_ParseTuple(_args, "i", &onoff)) + return NULL; + if ( _self->ob_freeit ) + old = 1; + if ( onoff ) + _self->ob_freeit = PyMac_AutoDisposeHandle; + else + _self->ob_freeit = NULL; + return Py_BuildValue("i", old); + +} + static PyMethodDef ResObj_methods[] = { {"HomeResFile", (PyCFunction)ResObj_HomeResFile, 1, "() -> (short _rv)"}, @@ -503,6 +535,8 @@ static PyMethodDef ResObj_methods[] = { "Return this resource/handle as a Menu"}, {"LoadResource", (PyCFunction)ResObj_LoadResource, 1, "() -> None"}, + {"AutoDispose", (PyCFunction)ResObj_AutoDispose, 1, + "(int)->int. Automatically DisposeHandle the object on Python object cleanup"}, {NULL, NULL, 0} }; @@ -1305,7 +1339,34 @@ static PyObject *Res_Resource(_self, _args) HLock(h); memcpy(*h, buf, len); HUnlock(h); - return (PyObject *)ResObj_New(h); + return ResObj_New(h); + +} + +static PyObject *Res_Handle(_self, _args) + PyObject *_self; + PyObject *_args; +{ + PyObject *_res = NULL; + + char *buf; + int len; + Handle h; + ResourceObject *rv; + + if (!PyArg_ParseTuple(_args, "s#", &buf, &len)) + return NULL; + h = NewHandle(len); + if ( h == NULL ) { + PyErr_NoMemory(); + return NULL; + } + HLock(h); + memcpy(*h, buf, len); + HUnlock(h); + rv = (ResourceObject *)ResObj_New(h); + rv->ob_freeit = PyMac_AutoDisposeHandle; + return (PyObject *)rv; } @@ -1377,7 +1438,9 @@ static PyMethodDef Res_methods[] = { {"FSpCreateResFile", (PyCFunction)Res_FSpCreateResFile, 1, "(FSSpec spec, OSType creator, OSType fileType, ScriptCode scriptTag) -> None"}, {"Resource", (PyCFunction)Res_Resource, 1, - "Convert a string to a resource object.\n\nThe created resource object is actually just a handle.\nApply AddResource() to write it to a resource file.\n"}, + "Convert a string to a resource object.\n\nThe created resource object is actually just a handle,\napply AddResource() to write it to a resource file.\nSee also the Handle() docstring.\n"}, + {"Handle", (PyCFunction)Res_Handle, 1, + "Convert a string to a Handle object.\n\nResource() and Handle() are very similar, but objects created with Handle() are\nby default automatically DisposeHandle()d upon object cleanup. Use AutoDispose()\nto change this.\n"}, {NULL, NULL, 0} }; @@ -1422,7 +1485,6 @@ OptResObj_Convert(v, p_itself) } - void initRes() { PyObject *m; diff --git a/Mac/Modules/res/resedit.py b/Mac/Modules/res/resedit.py index 42966e4..1684870 100644 --- a/Mac/Modules/res/resedit.py +++ b/Mac/Modules/res/resedit.py @@ -13,14 +13,45 @@ if ( h == NULL ) { HLock(h); memcpy(*h, buf, len); HUnlock(h); -return (PyObject *)ResObj_New(h); +return ResObj_New(h); """ f = ManualGenerator("Resource", resource_body) f.docstring = lambda: """Convert a string to a resource object. -The created resource object is actually just a handle. -Apply AddResource() to write it to a resource file. +The created resource object is actually just a handle, +apply AddResource() to write it to a resource file. +See also the Handle() docstring. +""" +functions.append(f) + +handle_body = """ +char *buf; +int len; +Handle h; +ResourceObject *rv; + +if (!PyArg_ParseTuple(_args, "s#", &buf, &len)) + return NULL; +h = NewHandle(len); +if ( h == NULL ) { + PyErr_NoMemory(); + return NULL; +} +HLock(h); +memcpy(*h, buf, len); +HUnlock(h); +rv = (ResourceObject *)ResObj_New(h); +rv->ob_freeit = PyMac_AutoDisposeHandle; +return (PyObject *)rv; +""" + +f = ManualGenerator("Handle", handle_body) +f.docstring = lambda: """Convert a string to a Handle object. + +Resource() and Handle() are very similar, but objects created with Handle() are +by default automatically DisposeHandle()d upon object cleanup. Use AutoDispose() +to change this. """ functions.append(f) @@ -46,3 +77,22 @@ f = ResMethod(void, 'LoadResource', (Handle, 'theResource', InMode), ) resmethods.append(f) + +# +# A method to set the auto-dispose flag +# +AutoDispose_body = """ +int onoff, old = 0; +if (!PyArg_ParseTuple(_args, "i", &onoff)) + return NULL; +if ( _self->ob_freeit ) + old = 1; +if ( onoff ) + _self->ob_freeit = PyMac_AutoDisposeHandle; +else + _self->ob_freeit = NULL; +return Py_BuildValue("i", old); +""" +f = ManualGenerator("AutoDispose", AutoDispose_body) +f.docstring = lambda: "(int)->int. Automatically DisposeHandle the object on Python object cleanup" +resmethods.append(f) diff --git a/Mac/Modules/res/ressupport.py b/Mac/Modules/res/ressupport.py index c0466a7..10e2724 100644 --- a/Mac/Modules/res/ressupport.py +++ b/Mac/Modules/res/ressupport.py @@ -25,6 +25,13 @@ includestuff = includestuff + """ #include #define resNotFound -192 /* Can't include because of Python's "errors.h" */ + +/* Function to dispose a resource, with a "normal" calling sequence */ +static void +PyMac_AutoDisposeHandle(Handle h) +{ + DisposeHandle(h); +} """ finalstuff = finalstuff + """ @@ -65,7 +72,6 @@ OptResObj_Convert(v, p_itself) PyErr_SetString(PyExc_TypeError, "Resource required"); return 0; } - """ initstuff = initstuff + """ @@ -120,7 +126,7 @@ ResObj_setattr(self, name, value) } """ -class ResDefiniton(GlobalObjectDefinition): +class ResDefinition(GlobalObjectDefinition): def outputCheckNewArg(self): Output("if (itself == NULL) return PyMac_Error(resNotFound);") @@ -145,8 +151,23 @@ class ResDefiniton(GlobalObjectDefinition): def outputSetattr(self): Output(setattrCode) + def outputStructMembers(self): + GlobalObjectDefinition.outputStructMembers(self) + Output("void (*ob_freeit)(%s ptr);", self.itselftype) + + def outputInitStructMembers(self): + GlobalObjectDefinition.outputInitStructMembers(self) + Output("it->ob_freeit = NULL;") + + def outputCleanupStructMembers(self): + Output("if (self->ob_freeit && self->ob_itself)") + OutLbrace() + Output("self->ob_freeit(self->ob_itself);") + OutRbrace() + Output("self->ob_itself = NULL;") + -resobject = ResDefiniton('Resource', 'ResObj', 'Handle') +resobject = ResDefinition('Resource', 'ResObj', 'Handle') module.addobject(resobject) functions = [] -- cgit v0.12