mirror of
https://github.com/python/cpython.git
synced 2025-07-23 11:15:24 +00:00
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.
This commit is contained in:
parent
a17e0f1b61
commit
add03b62fd
3 changed files with 143 additions and 10 deletions
|
@ -47,6 +47,13 @@ extern PyObject *WinObj_WhichWindow(WindowPtr);
|
||||||
|
|
||||||
#define resNotFound -192 /* Can't include <Errors.h> because of Python's "errors.h" */
|
#define resNotFound -192 /* Can't include <Errors.h> 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;
|
static PyObject *Res_Error;
|
||||||
|
|
||||||
/* ---------------------- Object type Resource ---------------------- */
|
/* ---------------------- Object type Resource ---------------------- */
|
||||||
|
@ -58,6 +65,7 @@ PyTypeObject Resource_Type;
|
||||||
typedef struct ResourceObject {
|
typedef struct ResourceObject {
|
||||||
PyObject_HEAD
|
PyObject_HEAD
|
||||||
Handle ob_itself;
|
Handle ob_itself;
|
||||||
|
void (*ob_freeit)(Handle ptr);
|
||||||
} ResourceObject;
|
} ResourceObject;
|
||||||
|
|
||||||
PyObject *ResObj_New(itself)
|
PyObject *ResObj_New(itself)
|
||||||
|
@ -68,6 +76,7 @@ PyObject *ResObj_New(itself)
|
||||||
it = PyObject_NEW(ResourceObject, &Resource_Type);
|
it = PyObject_NEW(ResourceObject, &Resource_Type);
|
||||||
if (it == NULL) return NULL;
|
if (it == NULL) return NULL;
|
||||||
it->ob_itself = itself;
|
it->ob_itself = itself;
|
||||||
|
it->ob_freeit = NULL;
|
||||||
return (PyObject *)it;
|
return (PyObject *)it;
|
||||||
}
|
}
|
||||||
ResObj_Convert(v, p_itself)
|
ResObj_Convert(v, p_itself)
|
||||||
|
@ -97,7 +106,11 @@ ResObj_Convert(v, p_itself)
|
||||||
static void ResObj_dealloc(self)
|
static void ResObj_dealloc(self)
|
||||||
ResourceObject *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);
|
PyMem_DEL(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -462,6 +475,25 @@ static PyObject *ResObj_LoadResource(_self, _args)
|
||||||
return _res;
|
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[] = {
|
static PyMethodDef ResObj_methods[] = {
|
||||||
{"HomeResFile", (PyCFunction)ResObj_HomeResFile, 1,
|
{"HomeResFile", (PyCFunction)ResObj_HomeResFile, 1,
|
||||||
"() -> (short _rv)"},
|
"() -> (short _rv)"},
|
||||||
|
@ -503,6 +535,8 @@ static PyMethodDef ResObj_methods[] = {
|
||||||
"Return this resource/handle as a Menu"},
|
"Return this resource/handle as a Menu"},
|
||||||
{"LoadResource", (PyCFunction)ResObj_LoadResource, 1,
|
{"LoadResource", (PyCFunction)ResObj_LoadResource, 1,
|
||||||
"() -> None"},
|
"() -> None"},
|
||||||
|
{"AutoDispose", (PyCFunction)ResObj_AutoDispose, 1,
|
||||||
|
"(int)->int. Automatically DisposeHandle the object on Python object cleanup"},
|
||||||
{NULL, NULL, 0}
|
{NULL, NULL, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1305,7 +1339,34 @@ static PyObject *Res_Resource(_self, _args)
|
||||||
HLock(h);
|
HLock(h);
|
||||||
memcpy(*h, buf, len);
|
memcpy(*h, buf, len);
|
||||||
HUnlock(h);
|
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,
|
{"FSpCreateResFile", (PyCFunction)Res_FSpCreateResFile, 1,
|
||||||
"(FSSpec spec, OSType creator, OSType fileType, ScriptCode scriptTag) -> None"},
|
"(FSSpec spec, OSType creator, OSType fileType, ScriptCode scriptTag) -> None"},
|
||||||
{"Resource", (PyCFunction)Res_Resource, 1,
|
{"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}
|
{NULL, NULL, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1422,7 +1485,6 @@ OptResObj_Convert(v, p_itself)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void initRes()
|
void initRes()
|
||||||
{
|
{
|
||||||
PyObject *m;
|
PyObject *m;
|
||||||
|
|
|
@ -13,14 +13,45 @@ if ( h == NULL ) {
|
||||||
HLock(h);
|
HLock(h);
|
||||||
memcpy(*h, buf, len);
|
memcpy(*h, buf, len);
|
||||||
HUnlock(h);
|
HUnlock(h);
|
||||||
return (PyObject *)ResObj_New(h);
|
return ResObj_New(h);
|
||||||
"""
|
"""
|
||||||
|
|
||||||
f = ManualGenerator("Resource", resource_body)
|
f = ManualGenerator("Resource", resource_body)
|
||||||
f.docstring = lambda: """Convert a string to a resource object.
|
f.docstring = lambda: """Convert a string to a resource object.
|
||||||
|
|
||||||
The created resource object is actually just a handle.
|
The created resource object is actually just a handle,
|
||||||
Apply AddResource() to write it to a resource file.
|
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)
|
functions.append(f)
|
||||||
|
|
||||||
|
@ -46,3 +77,22 @@ f = ResMethod(void, 'LoadResource',
|
||||||
(Handle, 'theResource', InMode),
|
(Handle, 'theResource', InMode),
|
||||||
)
|
)
|
||||||
resmethods.append(f)
|
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)
|
||||||
|
|
|
@ -25,6 +25,13 @@ includestuff = includestuff + """
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#define resNotFound -192 /* Can't include <Errors.h> because of Python's "errors.h" */
|
#define resNotFound -192 /* Can't include <Errors.h> 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 + """
|
finalstuff = finalstuff + """
|
||||||
|
@ -65,7 +72,6 @@ OptResObj_Convert(v, p_itself)
|
||||||
PyErr_SetString(PyExc_TypeError, "Resource required");
|
PyErr_SetString(PyExc_TypeError, "Resource required");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
initstuff = initstuff + """
|
initstuff = initstuff + """
|
||||||
|
@ -120,7 +126,7 @@ ResObj_setattr(self, name, value)
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
class ResDefiniton(GlobalObjectDefinition):
|
class ResDefinition(GlobalObjectDefinition):
|
||||||
|
|
||||||
def outputCheckNewArg(self):
|
def outputCheckNewArg(self):
|
||||||
Output("if (itself == NULL) return PyMac_Error(resNotFound);")
|
Output("if (itself == NULL) return PyMac_Error(resNotFound);")
|
||||||
|
@ -145,8 +151,23 @@ class ResDefiniton(GlobalObjectDefinition):
|
||||||
def outputSetattr(self):
|
def outputSetattr(self):
|
||||||
Output(setattrCode)
|
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)
|
module.addobject(resobject)
|
||||||
|
|
||||||
functions = []
|
functions = []
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue