crude KVO setter for structs

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@35324 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
rfm 2012-07-27 16:48:49 +00:00
parent 52dbdbcf0e
commit e357aab701
8 changed files with 156 additions and 45 deletions

View file

@ -145,10 +145,6 @@ gs_find_best_typed_sel (SEL sel)
static IMP gs_objc_msg_forward2 (id receiver, SEL sel)
{
NSMutableData *frame;
cifframe_t *cframe;
ffi_closure *cclosure;
void *executable;
NSMethodSignature *sig = nil;
GSCodeBuffer *memory;
const char *types;
@ -206,38 +202,9 @@ static IMP gs_objc_msg_forward2 (id receiver, SEL sel)
}
}
/* Construct the frame and closure. */
/* Note: We obtain cframe here, but it's passed to GSFFIInvocationCallback
where it becomes owned by the callback invocation, so we don't have to
worry about ownership */
frame = cifframe_from_signature(sig);
cframe = [frame mutableBytes];
/* Autorelease the closure through GSAutoreleasedBuffer */
memory = cifframe_closure(sig, GSFFIInvocationCallback);
memory = [GSCodeBuffer memoryWithSize: sizeof(ffi_closure)];
cclosure = [memory buffer];
executable = [memory executable];
if (cframe == NULL || cclosure == NULL)
{
[NSException raise: NSMallocException format: @"Allocating closure"];
}
#if HAVE_FFI_PREP_CLOSURE_LOC
if (ffi_prep_closure_loc(cclosure, &(cframe->cif),
GSFFIInvocationCallback, frame, executable) != FFI_OK)
{
[NSException raise: NSGenericException format: @"Preping closure"];
}
#else
executable = (void*)cclosure;
if (ffi_prep_closure(cclosure, &(cframe->cif),
GSFFIInvocationCallback, frame) != FFI_OK)
{
[NSException raise: NSGenericException format: @"Preping closure"];
}
#endif
[memory protect];
return (IMP)executable;
return (IMP)[memory executable];
}
static __attribute__ ((__unused__))

View file

@ -527,12 +527,14 @@ GSPrivateUnloadModule(FILE *errorStream,
unsigned size;
void *buffer;
void *executable;
id frame;
}
+ (GSCodeBuffer*) memoryWithSize: (NSUInteger)_size;
- (void*) buffer;
- (void*) executable;
- (id) initWithSize: (NSUInteger)_size;
- (void) protect;
- (void) setFrame: (id)aFrame;
@end
BOOL

View file

@ -71,6 +71,7 @@
- (void) dealloc
{
DESTROY(frame);
if (size > 0)
{
#if defined(HAVE_FFI_PREP_CLOSURE_LOC)
@ -173,6 +174,11 @@
#endif
#endif
}
- (void) setFrame: (id)aFrame
{
ASSIGN(frame, aFrame);
}
@end
static Class NSInvocation_abstract_class;

View file

@ -44,6 +44,10 @@
#import "GNUstepBase/NSObject+GNUstepBase.h"
#import "GSInvocation.h"
#if defined(USE_LIBFFI)
#import "cifframe.h"
#endif
/*
* IMPLEMENTATION NOTES
*
@ -385,6 +389,38 @@ replacementForClass(Class c)
return r;
}
#if defined(USE_LIBFFI)
static void
cifframe_callback(ffi_cif *cif, void *retp, void **args, void *user)
{
id obj;
SEL sel;
NSString *key;
Class c;
void (*imp)(id,SEL,void*);
obj = *(id *)args[0];
sel = *(SEL *)args[1];
c = [obj class];
imp = (void (*)(id,SEL,void*))[c instanceMethodForSelector: sel];
key = newKey(sel);
if ([c automaticallyNotifiesObserversForKey: key] == YES)
{
// pre setting code here
[obj willChangeValueForKey: key];
ffi_call(cif, imp, retp, args);
// post setting code here
[obj didChangeValueForKey: key];
}
else
{
ffi_call(cif, imp, retp, args);
}
RELEASE(key);
}
#endif
@implementation GSKVOReplacement
- (void) dealloc
{
@ -557,7 +593,15 @@ replacementForClass(Class c)
}
else
{
#if defined(USE_LIBFFI)
GSCodeBuffer *b;
b = cifframe_closure(sig, cifframe_callback);
[b retain];
imp = [b executable];
#else
imp = 0;
#endif
}
break;
default:

View file

@ -40,8 +40,9 @@
#endif
#endif
#include "Foundation/NSMethodSignature.h"
#include "GNUstepBase/DistributedObjects.h"
#import "Foundation/NSMethodSignature.h"
#import "GNUstepBase/DistributedObjects.h"
#import "GSPrivate.h"
typedef struct _cifframe_t {
ffi_cif cif;
@ -54,6 +55,8 @@ typedef struct _cifframe_t {
extern NSMutableData *cifframe_from_signature (NSMethodSignature *info);
extern GSCodeBuffer* cifframe_closure (NSMethodSignature *sig, void (*func)());
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,

View file

@ -40,6 +40,7 @@
#import "Foundation/NSException.h"
#import "Foundation/NSData.h"
#import "GSInvocation.h"
#import "GSPrivate.h"
#if defined(ALPHA) || (defined(MIPS) && (_MIPS_SIM == _ABIN32))
typedef long long smallret_t;
@ -529,6 +530,46 @@ cifframe_type(const char *typePtr, const char **advance)
return ftype;
}
GSCodeBuffer*
cifframe_closure (NSMethodSignature *sig, void (*cb)())
{
NSMutableData *frame;
cifframe_t *cframe;
ffi_closure *cclosure;
void *executable;
GSCodeBuffer *memory;
/* Construct the frame (stored in an NSMutableDate object) and sety it
* in a new closure.
*/
frame = cifframe_from_signature(sig);
cframe = [frame mutableBytes];
memory = [GSCodeBuffer memoryWithSize: sizeof(ffi_closure)];
[memory setFrame: frame];
cclosure = [memory buffer];
executable = [memory executable];
if (cframe == NULL || cclosure == NULL)
{
[NSException raise: NSMallocException format: @"Allocating closure"];
}
#if HAVE_FFI_PREP_CLOSURE_LOC
if (ffi_prep_closure_loc(cclosure, &(cframe->cif),
cb, frame, executable) != FFI_OK)
{
[NSException raise: NSGenericException format: @"Preping closure"];
}
#else
executable = (void*)cclosure;
if (ffi_prep_closure(cclosure, &(cframe->cif),
cb, frame) != FFI_OK)
{
[NSException raise: NSGenericException format: @"Preping closure"];
}
#endif
[memory protect];
return memory;
}
/*-------------------------------------------------------------------------*/
/* Functions for handling sending and receiving messages accross a
connection