mirror of
https://github.com/gnustep/libs-base.git
synced 2025-05-31 00:30:53 +00:00
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:
parent
52dbdbcf0e
commit
e357aab701
8 changed files with 156 additions and 45 deletions
|
@ -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__))
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue