mirror of
https://github.com/gnustep/libs-base.git
synced 2025-04-23 09:04:13 +00:00
Libffi support
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@13506 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
0a671f9dfb
commit
d88dda825c
18 changed files with 1525 additions and 748 deletions
15
ChangeLog
15
ChangeLog
|
@ -1,3 +1,18 @@
|
|||
2002-04-18 Adam Fedor <fedor@gnu.org>
|
||||
|
||||
* Minimally working libffi support. Needs work.
|
||||
* configure.in: Allow libffi to be enabled.
|
||||
* Source/GSFFIInvocation.m: Rewrite.
|
||||
* Source/NSConnection.m (-forwardInvocation:forProxy:): Add libffi
|
||||
function.
|
||||
* Source/NSInvocation.m: Fixup cifframe arg functions.
|
||||
* Source/cifframe.m: Rewrite.
|
||||
* Testing/nsinvocation.m: Bug fix.
|
||||
|
||||
* Documentation/coding-standards.texi: Remove info dir tag.
|
||||
* Documentation/gnustep-base.texi: Idem.
|
||||
* Resources/Languages/Slovak: New file.
|
||||
|
||||
Thu Apr 18 11:10:04 2002 Nicola Pero <n.pero@mi.flashnet.it>
|
||||
|
||||
* Headers/gnustep/base/NSObjCRuntime.h: Updated #defines and
|
||||
|
|
|
@ -4,9 +4,7 @@
|
|||
|
||||
@ifinfo
|
||||
@format
|
||||
START-INFO-DIR-ENTRY
|
||||
* Coding: (coding). Coding Standards for GNUstep Libraries
|
||||
END-INFO-DIR-ENTRY
|
||||
@end format
|
||||
@end ifinfo
|
||||
|
||||
|
|
|
@ -13,9 +13,7 @@ prindex for protocols, and clindex for classes.
|
|||
|
||||
@ifinfo
|
||||
@format
|
||||
START-INFO-DIR-ENTRY
|
||||
* gstep-base:: The GNUstep Base Library
|
||||
END-INFO-DIR-ENTRY
|
||||
@end format
|
||||
@end ifinfo
|
||||
|
||||
|
|
|
@ -6,9 +6,7 @@
|
|||
|
||||
@ifinfo
|
||||
@format
|
||||
START-INFO-DIR-ENTRY
|
||||
* GNUstep Zones: (gnustep-zones). Memory management in GNUstep.
|
||||
END-INFO-DIR-ENTRY
|
||||
@end format
|
||||
@end ifinfo
|
||||
|
||||
|
|
|
@ -48,4 +48,7 @@
|
|||
extern void
|
||||
GSFFCallInvokeWithTargetAndImp(NSInvocation *inv, id anObject, IMP imp);
|
||||
|
||||
extern void
|
||||
GSFFIInvokeWithTargetAndImp(NSInvocation *inv, id anObject, IMP imp);
|
||||
|
||||
#endif
|
||||
|
|
35
Resources/Languages/Slovak
Normal file
35
Resources/Languages/Slovak
Normal file
|
@ -0,0 +1,35 @@
|
|||
/* Slovak */
|
||||
{
|
||||
NSLanguageName = "Slovak";
|
||||
NSFormalName = "Slovensky";
|
||||
NSLanguageCode = "SK";
|
||||
NSParentContext = "Default";
|
||||
|
||||
NSCurrencySymbol = "Sk";
|
||||
NSInternationalCurrencyString = SKK;
|
||||
NSPositiveCurrencyFormatString = "9.999,00 $";
|
||||
NSNegativeCurrencyFormatString = "-9.999,00 $";
|
||||
|
||||
NSDecimalDigits = ("0", "1", "2", "3", "4", "5", "6", "7", "8", "9");
|
||||
NSDecimalSeparator = ",";
|
||||
|
||||
NSDateFormatString = "%A, %B %d, %Y";
|
||||
NSDateTimeOrdering = DMYH; /* resolve numbers in Day,Month,Year,Hour order */
|
||||
NSEarlierTimeDesignations = ("predch\u00e1dzaj\u00faci", "posledn\u00fd", "minul\u00fd", "sp\u00e4\u0165");
|
||||
NSHourNameDesignations = ((0, polnoc), (12, poludnie), (10, "r\u00e1no"), (14, poobede), (19, "ve\u010der"));
|
||||
NSLaterTimeDesignations = ("bud\u00faci");
|
||||
NSMonthNameArray = ("Janu\u00e1r", "Febru\u00e1r", Marec, "Apr\u00edl", "M\u00e1j", "J\u00fan", "J\u00fal", August, September, "Okt\u00f3ber", November, December);
|
||||
NSNextDayDesignations = (zajtra);
|
||||
NSNextNextDayDesignations = (pozajtra);
|
||||
NSPriorDayDesignations = ("v\u010dera");
|
||||
NSShortDateFormatString = "%d.%m.%Y"; /* "07.12.95" for example */
|
||||
NSShortMonthNameArray = (Jan, Feb, Mar, Apr, "M\u00e1j", "J\u00fan", "J\u00fal", Aug, Sep, Okt, Nov, Dec);
|
||||
NSShortTimeDateFormatString = "%d.%b.%Y %H:%M"; /* "07. Dec. 95 16:50 " for example */
|
||||
NSShortWeekDayNameArray = (Ne, Po, Ut, St, "\u0160t", Pi, So);
|
||||
NSThisDayDesignations = (dnes);
|
||||
NSThousandsSeparator = ".";
|
||||
NSTimeDateFormatString = "%a %b %d %Y %H:%M:%S %Z";
|
||||
NSTimeFormatString = "%H:%M:%S";
|
||||
NSWeekDayNameArray = ("Nede\u013ea", Pondelok, Utorok, Streda, "\u0160tvrtok", Piatok, Sobota);
|
||||
NSYearMonthWeekDesignations = (rok, mesiac, "t\u00fd\u017ede\u0148");
|
||||
}
|
|
@ -1057,3 +1057,4 @@ GSInvocationCallback (void *callback_data, va_alist args)
|
|||
return out_parameters;
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
Copyright (C) 2000 Free Software Foundation, Inc.
|
||||
|
||||
Written: Adam Fedor <fedor@gnu.org>
|
||||
Date: Nov 2000
|
||||
Date: Apr 2002
|
||||
|
||||
This file is part of the GNUstep Base Library.
|
||||
|
||||
|
@ -20,81 +20,536 @@
|
|||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
*/
|
||||
|
||||
#include <Foundation/NSException.h>
|
||||
#include <Foundation/NSCoder.h>
|
||||
#include <Foundation/NSDistantObject.h>
|
||||
#include <base/GSInvocation.h>
|
||||
#include <config.h>
|
||||
#include <mframe.h>
|
||||
#include <objc/objc-api.h>
|
||||
#include "cifframe.h"
|
||||
|
||||
/* The FFI library doesn't have closures (well it does, but only for ix86), so
|
||||
we still use a lot of the argframe (mframe) functions for things like
|
||||
forwarding
|
||||
*/
|
||||
#ifndef INLINE
|
||||
#define INLINE inline
|
||||
#endif
|
||||
|
||||
@implementation GSFFIInvocation
|
||||
#if defined(ALPHA) || (defined(MIPS) && (_MIPS_SIM == _ABIN32))
|
||||
typedef long long smallret_t;
|
||||
#else
|
||||
typedef int smallret_t;
|
||||
#endif
|
||||
|
||||
- (id) initWithArgframe: (arglist_t)frame selector: (SEL)aSelector
|
||||
typedef struct _NSInvocation_t {
|
||||
@defs(NSInvocation)
|
||||
} NSInvocation_t;
|
||||
|
||||
/* Function that implements the actual forwarding */
|
||||
typedef void (*ffi_closure_fun) (ffi_cif*,void*,void**,void*);
|
||||
|
||||
void GSFFIInvocationCallback(ffi_cif*, void*, void **, void*);
|
||||
|
||||
/*
|
||||
* If we are using the GNU ObjC runtime we could
|
||||
* simplify this function quite a lot because this
|
||||
* function is already present in the ObjC runtime.
|
||||
* However, it is not part of the public API, so
|
||||
* we work around it.
|
||||
*/
|
||||
|
||||
static INLINE Method_t
|
||||
gs_method_for_receiver_and_selector (id receiver, SEL sel)
|
||||
{
|
||||
const char *types;
|
||||
NSMethodSignature *newSig;
|
||||
|
||||
types = sel_get_type(aSelector);
|
||||
if (types == 0)
|
||||
if (receiver)
|
||||
{
|
||||
types = sel_get_type(sel_get_any_typed_uid(sel_get_name(aSelector)));
|
||||
if (object_is_instance (receiver))
|
||||
{
|
||||
return class_get_instance_method (object_get_class
|
||||
(receiver), sel);
|
||||
}
|
||||
else if (object_is_class (receiver))
|
||||
{
|
||||
return class_get_class_method (object_get_meta_class
|
||||
(receiver), sel);
|
||||
}
|
||||
}
|
||||
if (types == 0)
|
||||
{
|
||||
[NSException raise: NSInvalidArgumentException
|
||||
format: @"Couldn't find encoding type for selector %s.",
|
||||
sel_get_name(aSelector)];
|
||||
}
|
||||
newSig = [NSMethodSignature signatureWithObjCTypes: types];
|
||||
self = [self initWithMethodSignature: newSig];
|
||||
|
||||
if (self)
|
||||
return METHOD_NULL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Selectors are not unique, and not all selectors have
|
||||
* type information. This method tries to find the
|
||||
* best equivalent selector with type information.
|
||||
*
|
||||
* the conversion sel -> name -> sel
|
||||
* is not what we want. However
|
||||
* I can not see a way to dispose of the
|
||||
* name, except if we can access the
|
||||
* internal data structures of the runtime.
|
||||
*
|
||||
* If we can access the private data structures
|
||||
* we can also check for incompatible
|
||||
* return types between all equivalent selectors.
|
||||
*/
|
||||
|
||||
static INLINE SEL
|
||||
gs_find_best_typed_sel (SEL sel)
|
||||
{
|
||||
if (!sel_get_type (sel))
|
||||
{
|
||||
[self setSelector: aSelector];
|
||||
/*
|
||||
* Copy the _cframe we were given.
|
||||
*/
|
||||
if (frame)
|
||||
const char *name = sel_get_name (sel);
|
||||
|
||||
if (name)
|
||||
{
|
||||
int i;
|
||||
|
||||
mframe_get_arg(frame, &_info[1], &_target);
|
||||
for (i = 1; i <= _numArgs; i++)
|
||||
{
|
||||
mframe_get_arg(frame, &_info[i],
|
||||
((cifframe_t *)_cframe)->values[i-1]);
|
||||
}
|
||||
SEL tmp_sel = sel_get_any_typed_uid (name);
|
||||
if (sel_get_type (tmp_sel))
|
||||
return tmp_sel;
|
||||
}
|
||||
}
|
||||
return self;
|
||||
return sel;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is the de_signated initialiser.
|
||||
* Take the receiver into account for finding the best
|
||||
* selector. That is, we look if the receiver
|
||||
* implements the selector and the implementation
|
||||
* selector has type info. If both conditions
|
||||
* are satisfied, return this selector.
|
||||
*
|
||||
* In all other cases fallback
|
||||
* to gs_find_best_typed_sel ().
|
||||
*/
|
||||
static INLINE SEL
|
||||
gs_find_by_receiver_best_typed_sel (id receiver, SEL sel)
|
||||
{
|
||||
if (sel_get_type (sel))
|
||||
return sel;
|
||||
|
||||
if (receiver)
|
||||
{
|
||||
Method_t method;
|
||||
|
||||
method = gs_method_for_receiver_and_selector (receiver, sel);
|
||||
/* CHECKME: Can we assume that:
|
||||
(a) method_name is a selector (compare libobjc header files)
|
||||
(b) this selector IS really typed?
|
||||
At the moment I assume (a) but not (b)
|
||||
not assuming (b) is the reason for
|
||||
calling gs_find_best_typed_sel () even
|
||||
if we have an implementation.
|
||||
*/
|
||||
if (method)
|
||||
sel = method->method_name;
|
||||
}
|
||||
return gs_find_best_typed_sel (sel);
|
||||
}
|
||||
|
||||
@implementation GSFFIInvocation
|
||||
|
||||
static IMP gs_objc_msg_forward (SEL sel)
|
||||
{
|
||||
const char *sel_type;
|
||||
cifframe_t *cframe;
|
||||
ffi_closure *cclosure;
|
||||
|
||||
NSMethodSignature *sig;
|
||||
|
||||
/* Determine the method types so we can construct the frame. We may not
|
||||
get the right one, though. What to do then? Perhaps it can be fixed up
|
||||
in the callback, but only under limited circumstances.
|
||||
*/
|
||||
sel = gs_find_best_typed_sel (sel);
|
||||
sel_type = sel_get_type (sel);
|
||||
sig = nil;
|
||||
|
||||
if (sel_type)
|
||||
{
|
||||
sig = [NSMethodSignature signatureWithObjCTypes: sel_type];
|
||||
}
|
||||
|
||||
NSCAssert1(sig, @"No signature for selector %@", NSStringFromSelector(sel));
|
||||
|
||||
/* Construct the frame and closure. */
|
||||
/* Note: We alloc 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], NULL);
|
||||
/* FIXME: But how to we free this? */
|
||||
cclosure = NSZoneCalloc(NSDefaultMallocZone(), sizeof(ffi_closure), 1);
|
||||
if (cframe == NULL || cclosure == NULL)
|
||||
{
|
||||
[NSException raise: NSMallocException format: @"Allocating closure"];
|
||||
}
|
||||
if (ffi_prep_closure(cclosure, &(cframe->cif),
|
||||
GSFFIInvocationCallback, cframe) != FFI_OK)
|
||||
{
|
||||
[NSException raise: NSGenericException format: @"Preping closure"];
|
||||
}
|
||||
|
||||
return (IMP)cclosure;
|
||||
}
|
||||
|
||||
+ (void) load
|
||||
{
|
||||
__objc_msg_forward = gs_objc_msg_forward;
|
||||
}
|
||||
|
||||
- (id) initWithArgframe: (arglist_t)frame selector: (SEL)aSelector
|
||||
{
|
||||
/* We should never get here */
|
||||
NSDeallocateObject(self);
|
||||
[NSException raise: NSInternalInconsistencyException
|
||||
format: @"Runtime incorrectly configured to pass argframes"];
|
||||
return nil;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is the designated initialiser.
|
||||
*/
|
||||
- (id) initWithMethodSignature: (NSMethodSignature*)aSignature
|
||||
{
|
||||
_sig = RETAIN(aSignature);
|
||||
_numArgs = [aSignature numberOfArguments];
|
||||
_info = [aSignature methodInfo];
|
||||
_cframe = cifframe_from_sig([_sig methodType], &_retval);
|
||||
if (_retval == 0 && _info[0].size > 0)
|
||||
{
|
||||
_retval = NSZoneMalloc(NSDefaultMallocZone(), _info[0].size);
|
||||
}
|
||||
_cframe = cifframe_from_info(_info, _numArgs, &_retval);
|
||||
return self;
|
||||
}
|
||||
|
||||
/* Initializer used when we get a callback. uses the data provided by
|
||||
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
|
||||
{
|
||||
int i, offset;
|
||||
_sig = RETAIN(aSignature);
|
||||
_numArgs = [aSignature numberOfArguments];
|
||||
_info = [aSignature methodInfo];
|
||||
_cframe = frame;
|
||||
((cifframe_t *)_cframe)->cif = *cif;
|
||||
((cifframe_t *)_cframe)->values = vals;
|
||||
|
||||
/* Insert the values into the value array.
|
||||
FIXME: I don't think this is correct for structures. */
|
||||
offset = 0;
|
||||
for (i = 0; i < ((cifframe_t *)_cframe)->nargs; i++)
|
||||
{
|
||||
((cifframe_t *)_cframe)->values[i] = *vals + offset;
|
||||
|
||||
offset += MAX(((cifframe_t *)_cframe)->arg_types[i]->size,
|
||||
sizeof(smallret_t));
|
||||
}
|
||||
_retval = retp;
|
||||
return self;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is implemented as a function so it can be used by other
|
||||
* routines (like the DO forwarding)
|
||||
*/
|
||||
void
|
||||
GSFFIInvokeWithTargetAndImp(NSInvocation *_inv, id anObject, IMP imp)
|
||||
{
|
||||
int i;
|
||||
NSInvocation_t *inv = (NSInvocation_t*)_inv;
|
||||
|
||||
/* Some arguments need to be promoted to be passed correctly */
|
||||
for (i = 2; i < inv->_numArgs; i++)
|
||||
{
|
||||
const char *type = inv->_info[i+1].type;
|
||||
cifframe_encode_arg(type, cifframe_arg_addr(inv->_cframe, i));
|
||||
}
|
||||
|
||||
/* Do it */
|
||||
ffi_call(inv->_cframe, imp, (inv->_retval),
|
||||
((cifframe_t *)inv->_cframe)->values);
|
||||
|
||||
/* Don't decode the return value here */
|
||||
}
|
||||
|
||||
- (void) invokeWithTarget: (id)anObject
|
||||
{
|
||||
id old_target;
|
||||
IMP imp;
|
||||
|
||||
/*
|
||||
* A message to a nil object returns nil.
|
||||
*/
|
||||
if (anObject == nil)
|
||||
{
|
||||
if (_retval)
|
||||
memset(_retval, '\0', _info[0].size); /* Clear return value */
|
||||
return;
|
||||
}
|
||||
|
||||
NSAssert(_selector != 0, @"you must set the selector before invoking");
|
||||
|
||||
/*
|
||||
* Temporarily set new target and copy it (and the selector) into the
|
||||
* _cframe.
|
||||
*/
|
||||
old_target = RETAIN(_target);
|
||||
[self setTarget: anObject];
|
||||
|
||||
cifframe_set_arg((cifframe_t *)_cframe, 0, &_target, _info[1].size);
|
||||
cifframe_set_arg((cifframe_t *)_cframe, 1, &_selector, _info[2].size);
|
||||
|
||||
if (_sendToSuper == YES)
|
||||
{
|
||||
Super s;
|
||||
|
||||
s.self = _target;
|
||||
if (GSObjCIsInstance(_target))
|
||||
s.class = class_get_super_class(GSObjCClass(_target));
|
||||
else
|
||||
s.class = class_get_super_class((Class)_target);
|
||||
imp = objc_msg_lookup_super(&s, _selector);
|
||||
}
|
||||
else
|
||||
{
|
||||
imp = method_get_imp(object_is_instance(_target) ?
|
||||
class_get_instance_method(
|
||||
((struct objc_class*)_target)->class_pointer, _selector)
|
||||
: class_get_class_method(
|
||||
((struct objc_class*)_target)->class_pointer, _selector));
|
||||
/*
|
||||
* If fast lookup failed, we may be forwarding or something ...
|
||||
*/
|
||||
if (imp == 0)
|
||||
{
|
||||
imp = objc_msg_lookup(_target, _selector);
|
||||
}
|
||||
}
|
||||
|
||||
[self setTarget: old_target];
|
||||
RELEASE(old_target);
|
||||
|
||||
GSFFIInvokeWithTargetAndImp(self, anObject, imp);
|
||||
|
||||
/* Decode the return value */
|
||||
if (*_info[0].type != _C_VOID)
|
||||
cifframe_decode_arg(_info[0].type, _retval);
|
||||
_validReturn = YES;
|
||||
}
|
||||
|
||||
- (void*) returnFrame: (arglist_t)argFrame
|
||||
{
|
||||
return mframe_handle_return(_info[0].type, _retval, argFrame);
|
||||
return _retval;
|
||||
}
|
||||
@end
|
||||
|
||||
void
|
||||
GSFFIInvocationCallback(ffi_cif *cif, void *retp, void **args, void *user)
|
||||
{
|
||||
id obj;
|
||||
SEL selector;
|
||||
GSFFIInvocation *invocation;
|
||||
NSMethodSignature *sig;
|
||||
Method_t fwdInvMethod;
|
||||
|
||||
memcpy(&obj, *args, sizeof(id));
|
||||
memcpy(&selector, *args+sizeof(id *), sizeof(SEL));
|
||||
|
||||
fwdInvMethod = gs_method_for_receiver_and_selector
|
||||
(obj, @selector (forwardInvocation:));
|
||||
|
||||
if (!fwdInvMethod)
|
||||
{
|
||||
NSCAssert2 (0, @"GSFFIInvocation: Class '%s' does not respond"
|
||||
@" to forwardInvocation: for '%s'",
|
||||
object_get_class_name (obj), sel_get_name(selector));
|
||||
}
|
||||
|
||||
selector = gs_find_by_receiver_best_typed_sel (obj, selector);
|
||||
sig = nil;
|
||||
|
||||
if (sel_get_type (selector))
|
||||
{
|
||||
sig = [NSMethodSignature signatureWithObjCTypes: sel_get_type(selector)];
|
||||
}
|
||||
|
||||
if (!sig)
|
||||
{
|
||||
sig = [obj methodSignatureForSelector: selector];
|
||||
}
|
||||
|
||||
NSCAssert1(sig, @"No signature for selector %@",
|
||||
NSStringFromSelector(selector));
|
||||
|
||||
invocation = [[GSFFIInvocation alloc] initWithCallback: cif
|
||||
returnp: retp
|
||||
values: args
|
||||
frame: user
|
||||
signature: sig];
|
||||
AUTORELEASE(invocation);
|
||||
[invocation setTarget: obj];
|
||||
[invocation setSelector: selector];
|
||||
|
||||
/*
|
||||
* Now do it.
|
||||
* The next line is equivalent to
|
||||
*
|
||||
* [obj forwardInvocation: invocation];
|
||||
*
|
||||
* but we have already the Method_t for forwardInvocation
|
||||
* so the line below is somewhat faster. */
|
||||
fwdInvMethod->method_imp (obj, fwdInvMethod->method_name, invocation);
|
||||
|
||||
/* We need to (re)encode the return type for it's trip back. */
|
||||
if (retp)
|
||||
cifframe_encode_arg([sig methodReturnType], retp);
|
||||
}
|
||||
|
||||
@implementation NSInvocation (DistantCoding)
|
||||
|
||||
/* An internal method used to help NSConnections code invocations
|
||||
to send over the wire */
|
||||
- (BOOL) encodeWithDistantCoder: (NSCoder*)coder passPointers: (BOOL)passp
|
||||
{
|
||||
int i;
|
||||
BOOL out_parameters = NO;
|
||||
const char *type = [_sig methodType];
|
||||
|
||||
[coder encodeValueOfObjCType: @encode(char*) at: &type];
|
||||
|
||||
for (i = 0; i < _numArgs; i++)
|
||||
{
|
||||
int flags = _info[i+1].qual;
|
||||
const char *type = _info[i+1].type;
|
||||
void *datum;
|
||||
|
||||
if (i == 0)
|
||||
{
|
||||
datum = &_target;
|
||||
}
|
||||
else if (i == 1)
|
||||
{
|
||||
datum = &_selector;
|
||||
}
|
||||
else
|
||||
{
|
||||
datum = cifframe_arg_addr((cifframe_t *)_cframe, i);
|
||||
}
|
||||
|
||||
/*
|
||||
* Decide how, (or whether or not), to encode the argument
|
||||
* depending on its FLAGS and TYPE. Only the first two cases
|
||||
* involve parameters that may potentially be passed by
|
||||
* reference, and thus only the first two may change the value
|
||||
* of OUT_PARAMETERS.
|
||||
*/
|
||||
|
||||
switch (*type)
|
||||
{
|
||||
case _C_ID:
|
||||
if (flags & _F_BYCOPY)
|
||||
{
|
||||
[coder encodeBycopyObject: *(id*)datum];
|
||||
}
|
||||
#ifdef _F_BYREF
|
||||
else if (flags & _F_BYREF)
|
||||
{
|
||||
[coder encodeByrefObject: *(id*)datum];
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
[coder encodeObject: *(id*)datum];
|
||||
}
|
||||
break;
|
||||
case _C_CHARPTR:
|
||||
/*
|
||||
* Handle a (char*) argument.
|
||||
* If the char* is qualified as an OUT parameter, or if it
|
||||
* not explicitly qualified as an IN parameter, then we will
|
||||
* have to get this char* again after the method is run,
|
||||
* because the method may have changed it. Set
|
||||
* OUT_PARAMETERS accordingly.
|
||||
*/
|
||||
if ((flags & _F_OUT) || !(flags & _F_IN))
|
||||
{
|
||||
out_parameters = YES;
|
||||
}
|
||||
/*
|
||||
* If the char* is qualified as an IN parameter, or not
|
||||
* explicity qualified as an OUT parameter, then encode
|
||||
* it.
|
||||
*/
|
||||
if ((flags & _F_IN) || !(flags & _F_OUT))
|
||||
{
|
||||
[coder encodeValueOfObjCType: type at: datum];
|
||||
}
|
||||
break;
|
||||
|
||||
case _C_PTR:
|
||||
/*
|
||||
* If the pointer's value is qualified as an OUT parameter,
|
||||
* or if it not explicitly qualified as an IN parameter,
|
||||
* then we will have to get the value pointed to again after
|
||||
* the method is run, because the method may have changed
|
||||
* it. Set OUT_PARAMETERS accordingly.
|
||||
*/
|
||||
if ((flags & _F_OUT) || !(flags & _F_IN))
|
||||
{
|
||||
out_parameters = YES;
|
||||
}
|
||||
if (passp)
|
||||
{
|
||||
if ((flags & _F_IN) || !(flags & _F_OUT))
|
||||
{
|
||||
[coder encodeValueOfObjCType: type at: datum];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Handle an argument that is a pointer to a non-char. But
|
||||
* (void*) and (anything**) is not allowed.
|
||||
* The argument is a pointer to something; increment TYPE
|
||||
* so we can see what it is a pointer to.
|
||||
*/
|
||||
type++;
|
||||
/*
|
||||
* If the pointer's value is qualified as an IN parameter,
|
||||
* or not explicity qualified as an OUT parameter, then
|
||||
* encode it.
|
||||
*/
|
||||
if ((flags & _F_IN) || !(flags & _F_OUT))
|
||||
{
|
||||
[coder encodeValueOfObjCType: type at: *(void**)datum];
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case _C_STRUCT_B:
|
||||
case _C_UNION_B:
|
||||
case _C_ARY_B:
|
||||
/*
|
||||
* Handle struct and array arguments.
|
||||
* Whether DATUM points to the data, or points to a pointer
|
||||
* that points to the data, depends on the value of
|
||||
* CALLFRAME_STRUCT_BYREF. Do the right thing
|
||||
* so that ENCODER gets a pointer to directly to the data.
|
||||
*/
|
||||
[coder encodeValueOfObjCType: type at: datum];
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Handle arguments of all other types. */
|
||||
[coder encodeValueOfObjCType: type at: datum];
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Return a BOOL indicating whether or not there are parameters that
|
||||
* were passed by reference; we will need to get those values again
|
||||
* after the method has finished executing because the execution of
|
||||
* the method may have changed them.
|
||||
*/
|
||||
return out_parameters;
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -2004,7 +2004,9 @@ static void retEncoder (DOContext *ctxt)
|
|||
}
|
||||
else
|
||||
{
|
||||
#ifdef USE_FFCALL
|
||||
#ifdef USE_LIBFFI
|
||||
cifframe_build_return (inv, type, outParams, retDecoder, &ctxt);
|
||||
#elif defined(USE_FFCALL)
|
||||
callframe_build_return (inv, type, outParams, retDecoder, &ctxt);
|
||||
#endif
|
||||
/* Make sure we processed all arguments, and dismissed the IP.
|
||||
|
|
|
@ -37,7 +37,6 @@
|
|||
#include "callframe.h"
|
||||
#endif
|
||||
|
||||
|
||||
static Class NSInvocation_abstract_class;
|
||||
static Class NSInvocation_concrete_class;
|
||||
|
||||
|
@ -47,13 +46,15 @@ static Class NSInvocation_concrete_class;
|
|||
static inline void
|
||||
_get_arg(NSInvocation *inv, int index, void *buffer)
|
||||
{
|
||||
cifframe_get_arg((cifframe_t *)inv->_cframe, index, buffer);
|
||||
cifframe_get_arg((cifframe_t *)inv->_cframe, index, buffer,
|
||||
inv->_info[index+1].size);
|
||||
}
|
||||
|
||||
static inline void
|
||||
_set_arg(NSInvocation *inv, int index, void *buffer)
|
||||
{
|
||||
cifframe_set_arg((cifframe_t *)inv->_cframe, index, buffer);
|
||||
cifframe_set_arg((cifframe_t *)inv->_cframe, index, buffer,
|
||||
inv->_info[index+1].size);
|
||||
}
|
||||
|
||||
static inline void *
|
||||
|
@ -169,7 +170,7 @@ _arg_addr(NSInvocation *inv, int index)
|
|||
#if defined(USE_LIBFFI)
|
||||
if (_cframe)
|
||||
{
|
||||
cifframe_free((cifframe_t *)_cframe);
|
||||
NSZoneFree(NSDefaultMallocZone(), _cframe);
|
||||
_retval = 0; // Part of _cframe
|
||||
}
|
||||
#elif defined(USE_FFCALL)
|
||||
|
@ -478,21 +479,12 @@ _arg_addr(NSInvocation *inv, int index)
|
|||
|
||||
stack_argsize = [_sig frameLength];
|
||||
|
||||
#ifdef USE_LIBFFI
|
||||
ffi_call(&((cifframe_t *)_cframe)->cif, (void(*)(void))imp, _retval,
|
||||
((cifframe_t *)_cframe)->values);
|
||||
if (_info[0].size)
|
||||
{
|
||||
cifframe_decode_return(_info[0].type, _retval);
|
||||
}
|
||||
#else
|
||||
returned = __builtin_apply((void(*)(void))imp,
|
||||
(arglist_t)_cframe, stack_argsize);
|
||||
if (_info[0].size)
|
||||
{
|
||||
mframe_decode_return(_info[0].type, _retval, returned);
|
||||
}
|
||||
#endif
|
||||
_validReturn = YES;
|
||||
}
|
||||
|
||||
|
@ -659,9 +651,6 @@ _arg_addr(NSInvocation *inv, int index)
|
|||
unsigned size = _info[i].size;
|
||||
void *datum;
|
||||
|
||||
#ifdef USE_LIBFFI
|
||||
size = ((cifframe_t *)_cframe)->args[i-1]->size;
|
||||
#endif
|
||||
datum = _arg_addr(self, i-1);
|
||||
|
||||
#define CASE_TYPE(_C,_T) case _C: *(_T*)datum = va_arg (ap, _T); break
|
||||
|
|
|
@ -35,11 +35,6 @@ typedef long long smallret_t;
|
|||
typedef int smallret_t;
|
||||
#endif
|
||||
|
||||
/* Return the number of arguments that the method MTH expects. Note
|
||||
that all methods need two implicit arguments `self' and `_cmd'.
|
||||
From mframe.m */
|
||||
extern int method_types_get_number_of_arguments (const char *type);
|
||||
|
||||
extern BOOL sel_types_match(const char* t1, const char* t2);
|
||||
|
||||
callframe_t *
|
||||
|
|
|
@ -26,24 +26,32 @@
|
|||
#define cifframe_h_INCLUDE
|
||||
|
||||
#include <ffi.h>
|
||||
#include <base/preface.h>
|
||||
#include <Foundation/NSMethodSignature.h>
|
||||
#include <base/DistributedObjects.h>
|
||||
|
||||
typedef struct _cifframe_t {
|
||||
ffi_cif cif;
|
||||
int nargs;
|
||||
ffi_type *rtype;
|
||||
ffi_type **args;
|
||||
ffi_type **arg_types;
|
||||
void **values;
|
||||
} cifframe_t;
|
||||
|
||||
extern cifframe_t *cifframe_from_sig (const char *typePtr, void **retval);
|
||||
extern void cifframe_free(cifframe_t *cframe);
|
||||
extern void cifframe_set_arg(cifframe_t *cframe, int index, void *buffer);
|
||||
extern void cifframe_get_arg(cifframe_t *cframe, int index, void *buffer);
|
||||
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,
|
||||
int size);
|
||||
extern void *cifframe_arg_addr(cifframe_t *cframe, int index);
|
||||
extern BOOL cifframe_decode_return (const char *type, void* buffer);
|
||||
extern BOOL cifframe_decode_arg (const char *type, void* buffer);
|
||||
extern BOOL cifframe_encode_arg (const char *type, void* buffer);
|
||||
|
||||
extern void cifframe_do_call (DOContext *ctxt,
|
||||
void(*decoder)(DOContext*),
|
||||
void(*encoder)(DOContext*));
|
||||
extern void cifframe_build_return (NSInvocation *inv,
|
||||
const char *type,
|
||||
BOOL out_parameters,
|
||||
void(*decoder)(DOContext*),
|
||||
DOContext* ctxt);
|
||||
#endif
|
||||
|
|
1064
Source/cifframe.m
1064
Source/cifframe.m
File diff suppressed because it is too large
Load diff
|
@ -36,7 +36,7 @@
|
|||
#
|
||||
|
||||
# Additional flags to pass to the preprocessor
|
||||
ADDITIONAL_CPPFLAGS =
|
||||
ADDITIONAL_CPPFLAGS =
|
||||
|
||||
# Additional flags to pass to the Objective-C compiler
|
||||
ADDITIONAL_OBJCFLAGS = -g
|
||||
|
@ -54,7 +54,6 @@ ADDITIONAL_LDFLAGS =
|
|||
# Additional library directories the linker should search
|
||||
ADDITIONAL_LIB_DIRS = -L../Source/$(GNUSTEP_OBJ_DIR)
|
||||
|
||||
|
||||
ifeq ($(GNUSTEP_TARGET_OS),mingw32)
|
||||
BUNDLE_LIBS += -lgnustep-base -lobjc
|
||||
endif
|
||||
|
|
|
@ -164,6 +164,8 @@ typedef struct {
|
|||
d = [NSArchiver archivedDataWithRootObject: i];
|
||||
i = [NSUnarchiver unarchiveObjectWithData: d];
|
||||
l = [[i methodSignature] methodReturnLength];
|
||||
if (l < sizeof(void *))
|
||||
l = sizeof(void *);
|
||||
b = (void *)objc_malloc(l);
|
||||
[i getReturnValue: b];
|
||||
[inv setReturnValue: b];
|
||||
|
@ -194,8 +196,10 @@ main ()
|
|||
id p;
|
||||
NSAutoreleasePool *arp = [NSAutoreleasePool new];
|
||||
|
||||
printf("Starting\n");
|
||||
t = [Target new];
|
||||
p = [[MyProxy alloc] initWithTarget: t];
|
||||
printf("Calling proxy\n");
|
||||
[p loopInt: 1];
|
||||
|
||||
#define SETUP(X) \
|
||||
|
|
2
Version
2
Version
|
@ -7,7 +7,7 @@ GCC_VERSION=2.8.0
|
|||
# The version number of this release.
|
||||
MAJOR_VERSION=1
|
||||
MINOR_VERSION=3
|
||||
SUBMINOR_VERSION=0
|
||||
SUBMINOR_VERSION=1
|
||||
GNUSTEP_BASE_VERSION=${MAJOR_VERSION}.${MINOR_VERSION}.${SUBMINOR_VERSION}
|
||||
VERSION=${GNUSTEP_BASE_VERSION}
|
||||
|
||||
|
|
11
configure.in
11
configure.in
|
@ -852,12 +852,11 @@ AC_ARG_ENABLE(libffi,
|
|||
[ --enable-libffi Enable use of libffi library],,
|
||||
enable_libffi=no)
|
||||
if test $enable_libffi = yes; then
|
||||
AC_WARN(libffi support disabled)
|
||||
echo
|
||||
echo "GNUstep requires more functionality than the ffi library"
|
||||
echo "currently supports ... please use ffcall instead."
|
||||
echo "libffi support will be added when the ffi library improves"
|
||||
enable_libffi=no
|
||||
echo "WARNING !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
|
||||
echo "The libffi library is not fully supported in GNUstep"
|
||||
echo "please use ffcall instead, unless you would like to help."
|
||||
echo "debug it. Use with caution."
|
||||
echo "WARNING !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
|
||||
fi
|
||||
|
||||
AC_ARG_ENABLE(ffcall,
|
||||
|
|
Loading…
Reference in a new issue