From c5a763be4c735d9d390ec27db8bdd487bd736c75 Mon Sep 17 00:00:00 2001 From: fedor Date: Mon, 17 Feb 2003 05:06:02 +0000 Subject: [PATCH] Fix but in forwarded object return git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@15985 72102866-910b-0410-8b05-ffd578937521 --- ChangeLog | 8 ++------ Source/GSFFIInvocation.m | 21 ++++++++++++++++----- Source/cifframe.h | 4 ++-- Source/cifframe.m | 14 +++++++------- 4 files changed, 27 insertions(+), 20 deletions(-) diff --git a/ChangeLog b/ChangeLog index 37c4a6679..e3d93694a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3,12 +3,8 @@ * Version 1.5.2 * Documentation: Update. - * Source/cifframe.m (cifframe_from_info): Include retval in - cifframe_t struct not as pass-back argument. - * Source/GSFFIInvocation.m (-initWithMethodSignature:): Get retval - from cifframe. - (-initWithCallback:...): Idem. - (GSFFIInvocationCallback): Set return pointer in closure. + * Source/GSFFIInvocation.m (GSFFIInvocationCallback): Autorelease + and invalidate the return value object before returning. 2003-02-16 Richard Frith-Macdonald diff --git a/Source/GSFFIInvocation.m b/Source/GSFFIInvocation.m index 16bdae341..0667ea90f 100644 --- a/Source/GSFFIInvocation.m +++ b/Source/GSFFIInvocation.m @@ -169,7 +169,7 @@ static IMP gs_objc_msg_forward (SEL sel) /* Note: We malloc cframe here, but it's passed to GSFFIInvocationCallback where it becomes owned by the callback invocation, so we don't have to worry about freeing it */ - cframe = cifframe_from_info([sig methodInfo], [sig numberOfArguments]); + cframe = cifframe_from_info([sig methodInfo], [sig numberOfArguments], NULL); /* Autorelease the closure through fastMallocBuffer */ cclosure = (ffi_closure *)_fastMallocBuffer(sizeof(ffi_closure)); if (cframe == NULL || cclosure == NULL) @@ -212,8 +212,7 @@ static IMP gs_objc_msg_forward (SEL sel) _sig = RETAIN(aSignature); _numArgs = [aSignature numberOfArguments]; _info = [aSignature methodInfo]; - _cframe = cifframe_from_info(_info, _numArgs); - _retval = ((cifframe_t *)_cframe)->retval; + _cframe = cifframe_from_info(_info, _numArgs, &_retval); return self; } @@ -221,6 +220,7 @@ static IMP gs_objc_msg_forward (SEL sel) the callback. The cifframe was allocated by the forwarding function, but we own it now so we can free it */ - (id) initWithCallback: (ffi_cif *)cif + returnp: (void *)retp values: (void **)vals frame: (cifframe_t *)frame signature: (NSMethodSignature*)aSignature @@ -253,7 +253,7 @@ static IMP gs_objc_msg_forward (SEL sel) #else ((cifframe_t *)_cframe)->values = vals; #endif - _retval = ((cifframe_t *)_cframe)->retval; + _retval = retp; return self; } @@ -389,6 +389,7 @@ GSFFIInvocationCallback(ffi_cif *cif, void *retp, void **args, void *user) NSStringFromSelector(selector)); invocation = [[GSFFIInvocation alloc] initWithCallback: cif + returnp: retp values: args frame: user signature: sig]; @@ -406,8 +407,18 @@ GSFFIInvocationCallback(ffi_cif *cif, void *retp, void **args, void *user) * so the line below is somewhat faster. */ fwdInvMethod->method_imp (obj, fwdInvMethod->method_name, invocation); + /* Autorelease the invocation's return value (if it's an object) and + mark it as invalid, so it won't be released later. We have to do + this since the return value (retp) really belongs to the closure + not the invocation so it will be demallocd at the end of this call + */ + if ([sig methodReturnType] && *[sig methodReturnType] == _C_ID) + { + AUTORELEASE(*(id *)retp); + invocation->_validReturn = NO; + } + /* We need to (re)encode the return type for it's trip back. */ - retp = [invocation returnFrame: NULL]; if (retp) cifframe_encode_arg([sig methodReturnType], retp); } diff --git a/Source/cifframe.h b/Source/cifframe.h index 1148d7283..e56baf0af 100644 --- a/Source/cifframe.h +++ b/Source/cifframe.h @@ -34,10 +34,10 @@ typedef struct _cifframe_t { int nargs; ffi_type **arg_types; void **values; - void *retval; } cifframe_t; -extern cifframe_t *cifframe_from_info (NSArgumentInfo *info, int numargs); +extern cifframe_t *cifframe_from_info (NSArgumentInfo *info, int numargs, + void **retval); extern void cifframe_set_arg(cifframe_t *cframe, int index, void *buffer, int size); extern void cifframe_get_arg(cifframe_t *cframe, int index, void *buffer, diff --git a/Source/cifframe.m b/Source/cifframe.m index 81f8bcde4..5a8934d08 100644 --- a/Source/cifframe.m +++ b/Source/cifframe.m @@ -116,7 +116,7 @@ cifframe_guess_struct_size(ffi_type *stype) cifframe_t * -cifframe_from_info (NSArgumentInfo *info, int numargs) +cifframe_from_info (NSArgumentInfo *info, int numargs, void **retval) { unsigned size = sizeof(cifframe_t); unsigned align = __alignof(double); @@ -191,9 +191,9 @@ cifframe_from_info (NSArgumentInfo *info, int numargs) else full += MAX(rtype->size, sizeof(smallret_t)); cframe = buf = NSZoneCalloc(NSDefaultMallocZone(), full, 1); - if (cframe) + if (cframe && retval) { - cframe->retval = buf + pos; + *retval = buf + pos; } } else @@ -700,8 +700,8 @@ cifframe_do_call (DOContext *ctxt, /* Build the cif frame */ sig = [NSMethodSignature signatureWithObjCTypes: type]; - cframe = cifframe_from_info([sig methodInfo], [sig numberOfArguments]); - retval = cframe->retval; + cframe = cifframe_from_info([sig methodInfo], [sig numberOfArguments], + &retval); ctxt->datToFree = cframe; /* Put OBJECT and SELECTOR into the ARGFRAME. */ @@ -986,8 +986,8 @@ cifframe_build_return (NSInvocation *inv, /* Build the cif frame */ sig = [NSMethodSignature signatureWithObjCTypes: type]; - cframe = cifframe_from_info([sig methodInfo], [sig numberOfArguments]); - retval = cframe->retval; + cframe = cifframe_from_info([sig methodInfo], [sig numberOfArguments], + &retval); ctxt->datToFree = cframe; /* Get the return type qualifier flags, and the return type. */