3 // HigherOrderMessaging
5 // Created by Ofri Wolfus on 03/11/06.
6 // Copyright 2006-2007 Ofri Wolfus. All rights reserved.
8 // Redistribution and use in source and binary forms, with or without modification,
9 // are permitted provided that the following conditions are met:
11 // 1. Redistributions of source code must retain the above copyright
12 // notice, this list of conditions and the following disclaimer.
13 // 2. Redistributions in binary form must reproduce the above copyright
14 // notice, this list of conditions and the following disclaimer in the
15 // documentation and/or other materials provided with the distribution.
16 // 3. Neither the name of Ofri Wolfus nor the names of his contributors
17 // may be used to endorse or promote products derived from this software
18 // without specific prior written permission.
20 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23 // IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #ifndef _DP_OBJCRUNTIME_H
32 #define _DP_OBJCRUNTIME_H
35 // Compatibility with C*
37 #if !defined(__OBJC2__)
42 // Platform specific defs for externs
52 #define DP_EXTERN extern "C"
53 #define DP_PRIVATE_EXTERN __private_extern__
55 #define DP_EXTERN extern
56 #define DP_PRIVATE_EXTERN __private_extern__
65 #ifndef _CKBUILDING_DP_DLL
66 #define _CKWINDOWS_DLL_GOOP __declspec(dllimport)
68 #define _CKWINDOWS_DLL_GOOP __declspec(dllexport)
72 #define DP_EXTERN extern "C" _CKWINDOWS_DLL_GOOP
73 #define DP_PRIVATE_EXTERN extern
75 #define DP_EXTERN _CKWINDOWS_DLL_GOOP extern
76 #define DP_PRIVATE_EXTERN extern
83 #elif defined(SOLARIS)
86 #define DP_EXTERN extern "C"
87 #define DP_PRIVATE_EXTERN extern "C"
89 #define DP_EXTERN extern
90 #define DP_PRIVATE_EXTERN extern
98 #if !defined(DP_STATIC_INLINE)
99 #if defined (__GNUC__) && (__GNUC__ == 4)
100 #define DP_STATIC_INLINE static __inline__ __attribute__((always_inline))
102 #define DP_STATIC_INLINE static __inline__
109 #if !defined(DP_EXTERN_INLINE)
110 #define DP_EXTERN_INLINE extern __inline__
113 //===============================================
115 #pragma mark Runtime Versions Compatibility Layer
118 * This section contains a compatibility layer between Objective-C 1
119 * (MacOS X 10.4) and Objective-C 2.0 (MacOS X 10.5).
120 * Mostly, this layer implements the new (v2.0) API for the old
121 * (v1) runtime, as thew new API is much cleaner and simpler to
123 * In addition, a new type dp_marg_list is defined, that matches
124 * the runtime's marg_list type. As both types are interchangeable,
125 * you can freely use dp_marg_list instead of marg_list (which is
126 * the recommended way).
127 * WARNING: This API wasn't tested under ObjC 2.0 and might not
128 * even compile. Use at your own risk!
131 #ifndef _DP_OBJC_COMPATIBILITY_H
132 #define _DP_OBJC_COMPATIBILITY_H
135 /**************************************
137 **************************************/
138 //#pragma mark Objective-C I
139 /* Stuff that exist in the Objective-C 2 runtime, but not in v1 */
142 #import <objc/objc-class.h>
143 #import <objc/objc-runtime.h>
144 #import <objc/Protocol.h> // for objc_method_description
147 // Methods manipulation
149 #define method_getName(m) (m->method_name)
150 #define method_getImplementation(m) (m->method_imp)
151 #define method_getTypeEncoding(m) (m->method_types)
152 #define method_setImplementation(m, imp) ({IMP __r = m->method_imp; m->method_imp = imp; __r;})
154 DP_EXTERN
char *method_copyReturnType(Method m
);
155 DP_EXTERN
char *method_copyArgumentType(Method m
, unsigned int index
);
156 DP_EXTERN
void method_getReturnType(Method m
, char *dst
, size_t dst_len
);
157 DP_EXTERN
void method_getArgumentType(Method m
, unsigned int index
,
158 char *dst
, size_t dst_len
);
160 // struct objc_method_description *method_getDescription(Method m)
161 #define method_getDescription(m) \
163 struct objc_method_description __desc; \
164 __desc.name = method_getName(m); \
165 __desc.types = method_getTypeEncoding(m); \
170 // Class manipulation
172 #define class_getName(cls) (((Class)cls)->name)
173 #define class_getSuperclass(cls) (((Class)cls)->super_class)
174 #define class_getInstanceSize(cls) ( (size_t)(((Class)cls)->instance_size) )
175 DP_EXTERN Method
* class_copyMethodList(Class cls
, unsigned int *outCount
);
176 DP_EXTERN BOOL
class_addMethod(Class cls
, SEL name
, IMP imp
,
182 /* Shouldn't this work with the new runtime as well? */
183 #define sel_isEqual(s1, s2) (s1 == s2)
186 // Classes and objects inspection
189 #define class_isMetaClass(cls) ((((Class)cls)->info & CLS_META) != 0)
190 #define object_getClass(obj) (obj->isa)
192 DP_EXTERN BOOL
class_respondsToSelector(Class cls
, SEL sel
);
195 #define _CLS_IS_CLASS(cls) ((((Class)cls)->info & CLS_CLASS) != 0)
196 #define _CLS_IS_META(cls) ((((Class)cls)->info & CLS_META) != 0)
197 #define _CLS_GET_META(cls) (_CLS_IS_META(cls) ? cls : cls->isa)
206 /**************************************
208 **************************************/
209 //#pragma mark Objective-C II
210 /* Compatibility with the older Objective-C runtime */
213 #include <objc/runtime.h>
214 #include <objc/message.h>
215 #include <machine/types.h> // For uintptr_t
216 #include <malloc/malloc.h> // For malloc_size
223 // These are defined in the GNU runtime but not in Apple's runtime,
224 // although the characters are the same.
238 #define _C_BYCOPY 'O'
246 #define _C_ONEWAY 'V'
251 // Working with marg_list
255 #if defined(__ppc__) || defined(__ppc64__)
258 typedef ppc_marg_list dp_ppc_marg_list
;
259 typedef ppc64_marg_list dp_ppc64_marg_list
;
262 double fpParams
[13]; // F1..F13
263 uintptr_t linkage
[6]; // ignored by objc_msgSendv; do not modify
264 uintptr_t regParams
[8]; // R3..R10; objc_msgSendv ignores R3 and R4
265 uintptr_t stackParams
[0]; // variable-size
266 } *dp_ppc_marg_list
, *dp_ppc64_marg_list
;
269 #define dp_marg_size (13 * sizeof(double) + (6 + 8) * sizeof(uintptr_t))
270 #define dp_marg_var_space (8 * sizeof(uintptr_t) /* regParams */)
273 #elif defined(__i386__)
276 typedef x86_marg_list dp_x86_marg_list
;
277 typedef i386_marg_list dp_i386_marg_list
;
280 uintptr_t params
[0]; // variable-size
281 } *dp_x86_marg_list
, *dp_i386_marg_list
;
284 // i386 passes arguments on stack
285 #define dp_marg_size 0
286 #define dp_marg_var_space 0
289 #elif defined(__x86_64__)
292 typedef x86_64_marg_list dp_x86_64_marg_list
;
294 #define dp_marg_size ( (sizeof(double) + sizeof(char) * 16) * 8 /* fpParams */\
295 + sizeof(uintptr_t) * 10 /* r10 + rax + linkage + regParams */)
296 #define dp_marg_var_space (6 * sizeof(uintptr_t) /* regParams */)
299 # error x86-64 is not supported in ObjC 1
302 #else // PPC, PPC64, i386, x86-64
303 # error unknown architecture
304 #endif // PPC, PPC64, i386, x86-64
307 * This is the fixed size of the marg_list.
308 * This size plus the size returned from method_getSizeOfArguments()
309 * is the total size of the arguments list.
310 * Use dp_marg_alloc() for marg_list allocation.
312 #define dp_marg_prearg_size (dp_marg_size - dp_marg_var_space)
316 * If you need to work with marg_list, use dp_marg_list which works on all architectures
317 * and both on ObjC 1 and 2.
318 * An abstraction layer for modifying the contents of the arguments list is not yet
319 * supported, so you'll have to be very careful and read the function calling ABI
320 * of your target architectures.
322 #if defined(__ppc__) || defined(__ppc64__)
323 typedef dp_ppc_marg_list dp_marg_list
;
324 #elif defined(__i386__)
325 typedef dp_i386_marg_list dp_marg_list
;
326 #elif defined(__x86_64__)
327 typedef dp_x86_64_marg_list dp_marg_list
;
329 # error unknown architecture
332 #endif // _DP_OBJC_COMPATIBILITY_H
335 #pragma mark A simplified API for some parts of the runtime
338 // Size and alignment of types
341 #define sizeOfType(t...) ({ NSUInteger __s; NSGetSizeAndAlignment(t, &__s, NULL); __s; })
342 #define alignOfType(t...) ({ NSUInteger __s; NSGetSizeAndAlignment(t, NULL, &__s); __s; })
344 #define sizeOfType(t...) ({ unsigned int __s; NSGetSizeAndAlignment(t, &__s, NULL); __s; })
345 #define alignOfType(t...) ({ unsigned int __s; NSGetSizeAndAlignment(t, NULL, &__s); __s; })
352 DP_EXTERN
unsigned dp_getNumberOfArguments(const char *typedesc
);
353 DP_EXTERN
unsigned dp_getArgumentInfo(const char *typedesc
, int argIndex
, const char** type
, int* offset
);
354 DP_EXTERN
unsigned dp_getSizeOfArguments(const char *typedesc
);
355 DP_EXTERN
void dp_getReturnType(const char *typedesc
, char *dst
, size_t dst_len
);
359 // Classes and objects inspection
361 #define class_isClass(cls) class_isMetaClass(cls->isa)
362 DP_EXTERN BOOL
class_isSubclassOfClass(Class cls
, Class superCls
);
364 #define object_isInstance(obj) class_isClass(obj->isa)
365 #define object_getClass(obj) (obj->isa)
366 #define object_isKindOfClass(obj, superCls) class_isSubclassOfClass(object_getClass(obj), superCls)
368 // Handles both objects and classes
369 DP_EXTERN_INLINE BOOL
object_respondsToSelector(id object
, SEL sel
);
371 DP_EXTERN_INLINE Method
dp_getMethod(id obj
, SEL sel
);
373 // Returns a NULL terminated array of classes (it's up to you to release it)
374 DP_EXTERN_INLINE Class
*dp_copyClassList(void);
380 DP_EXTERN_INLINE
unsigned int sel_getNumberOfArguments(SEL sel
); // Always takes the self and _cmd arguments in count
384 // Allocation/copying of marg_list
387 #define dp_marg_malloc(argsSize) malloc(dp_marg_prearg_size + (7 + argsSize & ~7) /* <- huh? */)
389 #define dp_marg_alloc(method) dp_marg_malloc(method_getSizeOfArguments(method))
390 #define dp_marg_copy(margs, method) \
391 ({ marg_list __marg = dp_marg_alloc(method); memcpy(__marg, margs, malloc_size(__marg)); })
394 // Accessing integral types
396 #define dp_margGetObjectRef(margs, offset, type) \
397 ((type *)((char *)margs + dp_marg_prearg_size + offset))
399 #define dp_margGetObject(margs, offset, type) \
400 (*dp_margGetObjectRef(margs, offset, type))
402 #define dp_margSetObject(margs, offset, type, value) \
403 ( dp_margGetObject(margs, offset, type) = (value) )
410 DP_EXTERN id
dp_msgSendv(id target
, SEL sel
, marg_list args
);
413 #endif //_DP_OBJCRUNTIME_H