Hi,
I am working on a logging package for C and Objective-C .
To be able to keep syntax for logging macros the same in C functions
and ObjC methods,
I am trying to do:
id myself = localVariableAvailable(self) ? self : NULL
I tried to look at the first character of __FUNCTION__ and (if it is
'+' or '-')
call a combination of __builtin_return / __builtin_apply_args() to
retrieve the first argument.
This approach has two problems:
1. When used with -fomit-frame-pointer I had semi-reproducible crashes
on x86_64 a method returns void.
(gcc 4.0.1, OS X 10.5.1)
2. It doesn't work with methods returning structs, which is probably
because I use
a "fake" function (with a fixed return type) to be able to use
__builtin_return.
void *retself(void *self, void *_cmd)
{
return self;
}
void *getself(void *args)
{
__builtin_return( __builtin_apply((void (*)()) retself, args, 2 *
sizeof(void*) ) );
}
[for reference, my complete test code for OS X 10.5 is attached
below]
Can anyone think of a reliable approach to access "self" which will
gracefully
yield NULL when used outside a method ?
Thanks for your time, kind regards,
Bjoern
--- 8< ---
/*
gcc -fomit-frame-pointer -Os -arch i386 -arch ppc -framework
Foundation -mmacosx-version-min=10.4 -isysroot /Developer/SDKs/
MacOSX10.4u.sdk -o arg-rel arg.m
gcc -Os -arch x86_64 -arch ppc64 -framework Foundation -mmacosx-
version-min=10.5 -isysroot /Developer/SDKs/MacOSX10.5.sdk -o arg-64-
rel arg.m
*/
#include <stdio.h>
#import <Foundation/Foundation.h>
#define LP_ARGS __builtin_apply_args()
#define LP_FUNC __PRETTY_FUNCTION__
void *retself(void *self, void *_cmd)
{
return self;
}
void *getself(void *args)
{
__builtin_return( __builtin_apply((void (*)()) retself, args, 2 *
sizeof(void*) ) );
}
void logger(const char *tag, id realself, void *args)
{
id fakeself = (*tag =='+' || *tag == '-') ? getself(args) : NULL;
printf("%-40.40s: self: %p getself: %p\n", tag, realself, fakeself);
if( realself != fakeself ) { fprintf(stderr, "FAIL !!!!\n"); /
*exit(1);*/ }
}
void cFuncVoid(void)
{
logger(LP_FUNC, NULL, LP_ARGS);
}
int cFuncArgs(int a, int b)
{
logger(LP_FUNC, NULL, LP_ARGS);
return a+b;
}
@interface ArgTest : NSObject
- (float) xFromPoint: (NSPoint) p;
- (NSRect) rectFromPoint: (NSPoint) p width: (float) width height:
(int) height;
- (void) nop;
+ (void) classNop;
@end
@implementation ArgTest
- (float) xFromPoint: (NSPoint) p
{
logger(LP_FUNC, self, LP_ARGS);
return p.x;
}
- (NSRect) rectFromPoint: (NSPoint) p width: (float) width height:
(int) height
{
logger(LP_FUNC, self, LP_ARGS);
return NSMakeRect(p.x,p.y,width,height);
}
- (void) nop
{
logger(LP_FUNC, self, LP_ARGS);
}
+ (void) classNop
{
logger(LP_FUNC, self, LP_ARGS);
}
@end
int main(int argc, char **argv)
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
cFuncArgs(23,42);
ArgTest *a = [[ArgTest alloc] init];
float x = [a xFromPoint: NSMakePoint(1.2,3.4)];
printf("x: %f\n", x);
NSRect r = [a rectFromPoint: NSMakePoint(1.2,3.4) width: 5.6
height: 7.8];
printf("r: %s\n", [NSStringFromRect(r) UTF8String]);
[a nop];
[ArgTest classNop]; /* had semi-reproducible crashes with -fomit-
frame-pointer on x86_64 */
[pool release];
return 0;
}