From 025688a2d5442c3c2db604e51c7018ec8e9b6e45 Mon Sep 17 00:00:00 2001 From: theraven Date: Tue, 21 Sep 2010 13:51:47 +0000 Subject: [PATCH] Added property_getName(). Added non-portable API documentation. --- API | 134 ++++++++++++++++++++++++++++++++++++++++++++ objc/Availability.h | 8 +++ objc/capabilities.h | 8 ++- objc/runtime.h | 25 +++------ properties.m | 4 ++ 5 files changed, 160 insertions(+), 19 deletions(-) create mode 100644 API diff --git a/API b/API new file mode 100644 index 0000000..a65c0be --- /dev/null +++ b/API @@ -0,0 +1,134 @@ +GNUstep Runtime APIs +==================== + +The GNUstep Objective-C runtime aims to implement all of the APIs defined in +Apple's Objective-C Runtime Reference. That document should be taken as the +authoritative reference to the majority of the APIs exposed by this runtime. +Any discrepancies between the implementations in this runtime and the +documentation should be regarded as a bug in the runtime. + +In addition to these APIs, the runtime also exposes some non-portable APIs. +These are all marked as OBJC_NONPORTABLE in the headers. Many of these APIs +are also implemented in GNUstep's ObjectiveC2 framework, which uses the GCC +Objective-C runtime for the underlying implementation and provides a portable +set of APIs on top of the GCC runtime structures and functions. + +Runtime Capabilities +-------------------- + +The objc/capabilities.h header defines runtime capabilities. A copy of this +header is also present in the ObjectiveC2 framework, so you can conditionally +include either version. + +You can perform two sorts of checks using this header. Constants declared in +the header describe capabilities that the runtime may or may not implement. If +a capability is missing from this header, then it means that you are using an +old version of the runtime, which lacks any knowledge of the header. You can +use this to refuse to compile with old runtime versions. + +You can also use the objc_test_capability() function to test whether a +particular capability is present at run time. Several of the capabilities are +optional in this runtime, and may not be compiled in to a given install. If +you require a particular capability, you can use the OBJC_REQUIRE_CAPABILITY() +macro to insert a load function that will abort if the capability is not present. + +This shows how to refuse to compile or run with versions of the runtime that do +not support type-dependent dispatch: + + #ifndef OBJC_CAP_TYPE_DEPENDENT_DISPATCH + # error Type-dependent dispatch support required! + #else + OBJC_REQUIRE_CAPABILITY(OBJC_CAP_TYPE_DEPENDENT_DISPATCH); + #endif + +Typed Selectors +--------------- + +Like the GCC runtime, this runtime uses typed selectors. In recent versions, +message lookup is also dependent on the type of the selector by default. This +can be disabled by not defining the TYPE_DEPENDENT_DISPATCH macro when +building. When using GNU make, you can get name-dependent dispatch by doing: + + $ gmake tdd=no + +This is strongly discouraged. It will give compatibility with the semantics of +the NeXT, Apple, and GCC runtimes, however these semantics include random stack +corruption from valid code. + +There are three functions for dealing with typed selectors. The first two are +direct equivalents of other functions. + + SEL sel_registerTypedName_np(const char *selName, const char *types); + +sel_registerName() will register an untyped selector. This variant registers a +typed selector, using the specified name and type encoding. + + const char *sel_getType_np(SEL aSel); + +This function simply returns the type encoding of the given selector, or NULL for a typed selector. + + unsigned sel_copyTypes_np(const char *selName, + const char **types, + unsigned count); + +This function copies *all* of the type encodings for a given selector name. +Generally, there are not many of these. In a well-written program, there will +be exactly one type encoding for a given selector. In a typical program, there +will be 1-3. It is not worth allocating a buffer on the heap for most cases, +so this function is designed to take a stack buffer. + +Unlike other functions in the runtime, this always returns the total number of +type encodings, not the number that were found. This means that you can call +it once with a smallish on-stack buffer and then call it again with a +malloc()'d buffer if there are a lot of encodings for a specific selector, as +follows. + + char *t[16]; + char *types = t; + unsigned total = sel_copyTypes_np("alloc", types, total); + if (total > 16) + { + types = calloc(sizeof(char*), total); + sel_copyTypes_np("alloc", types, total); + } + // Do stuff with the types. + if (total > 16) + { + free(types); + } + + +**Note**: This runtime does not provide any equivalent of the GCC runtime's +sel_get_typed_uid() or sel_get_any_typed_uid(). This is intentional. It is +impossible to use these functions correctly and they should never have been +made part of the public API. + +Message Sending +--------------- + +For ABI compatibility with the GCC runtime, this runtime implements the +objc_msg_lookup() and objc_msg_lookup_super() functions used to implement +message sending. + +The new ABI uses the objc_msg_lookup_sender() function in place of +objc_msg_lookup(). This allows fast proxies and caching of the lookup result +at the callsite. You can find more a detailed explanation of how this works in +the README file. + +This runtime also provides this semi-private function, which can be of use in +implementing parts of the Foundation framework and similar low-level libraries: + + struct objc_slot* objc_get_slot(Class cls, SEL selector); + +This looks up the slot for a given selector, without invoking any forwarding +mechanisms. This is most useful for quickly finding the type encoding of a +method (e.g. for implementing forwarding). The lookup is as fast as a normal +message lookup, and the types field of the returned slot provides the type +encoding. This is significantly faster than using class_getInstanceMethod(), +which needs to perform a linear search along a list (O(1) vs O(n)). + +Hooks +----- + +All of the callback hooks provided by this runtime are described in +objc/hooks.h. diff --git a/objc/Availability.h b/objc/Availability.h index 81d4cf9..408b998 100644 --- a/objc/Availability.h +++ b/objc/Availability.h @@ -10,3 +10,11 @@ #else # define OBJC_DEPRECATED __attribute__((deprecated)) #endif + +#ifdef ERROR_UNSUPPORTED_RUNTIME_FUNCTIONS +# define OBJC_GNUSTEP_RUNTIME_UNSUPPORTED(x) \ + __attribute__((error(x " not supported by this runtime"))) +#else +# define OBJC_GNUSTEP_RUNTIME_UNSUPPORTED(x) +#endif + diff --git a/objc/capabilities.h b/objc/capabilities.h index f123162..84f5771 100644 --- a/objc/capabilities.h +++ b/objc/capabilities.h @@ -12,6 +12,12 @@ * although they are present in the header and understood by the runtime, they * may not be supported by the installed runtime. */ +#include "Availability.h" + +#ifndef __GNUSTEP_RUNTIME__ +# define __GNUSTEP_RUNTIME__ +#endif + /** * The runtime supports zero-cost exceptions. @@ -68,4 +74,4 @@ * Run time feature test. This function returns 1 if the runtime supports the * specified feature or 0 if it does not. */ -int objc_test_capability(int x); +int objc_test_capability(int x) OBJC_NONPORTABLE; diff --git a/objc/runtime.h b/objc/runtime.h index 83378c7..3eb6ec8 100644 --- a/objc/runtime.h +++ b/objc/runtime.h @@ -1,9 +1,9 @@ #ifndef __LIBOBJC_RUNTIME_H_INCLUDED__ #define __LIBOBJC_RUNTIME_H_INCLUDED__ -// If __LEGACY_GNU_MODE__ is defined then we include the old GNU runtime header -// instead of this one -#define __GNUSTEP_RUNTIME__ +#ifndef __GNUSTEP_RUNTIME__ +# define __GNUSTEP_RUNTIME__ +#endif @@ -12,13 +12,6 @@ #include #include "Availability.h" -#ifdef ERROR_UNSUPPORTED_RUNTIME_FUNCTIONS -# define OBJC_GNUSTEP_RUNTIME_UNSUPPORTED(x) \ - __attribute__((error(x " not supported by this runtime"))) -#else -# define OBJC_GNUSTEP_RUNTIME_UNSUPPORTED(x) -#endif - // Undo GNUstep substitutions #ifdef class_setVersion # undef class_setVersion @@ -260,8 +253,10 @@ Class object_setClass(id obj, Class cls); const char *object_getClassName(id obj); -IMP objc_msg_lookup(id, SEL); -IMP objc_msg_lookup_super(struct objc_super*, SEL); +IMP objc_msg_lookup(id, SEL) OBJC_NONPORTABLE; +IMP objc_msg_lookup_super(struct objc_super*, SEL) OBJC_NONPORTABLE; + +const char *property_getName(objc_property_t property); BOOL protocol_conformsToProtocol(Protocol *p, Protocol *other); @@ -316,12 +311,6 @@ const char *sel_getType_np(SEL aSel) OBJC_NONPORTABLE; */ unsigned sel_copyTypes_np(const char *selName, const char **types, unsigned count) OBJC_NONPORTABLE; -/** - * Copies all of the type encodings associated with a given selector name into - * types, returning the number of types. - */ -unsigned sel_copyTypes(const char *selName, const char **types, unsigned count); - /** * New ABI lookup function. Receiver may be modified during lookup or proxy * forwarding and the sender may affect how lookup occurs. diff --git a/properties.m b/properties.m index ffad0fb..c090825 100644 --- a/properties.m +++ b/properties.m @@ -172,3 +172,7 @@ objc_property_t* class_copyPropertyList(Class cls, unsigned int *outCount) return list; } +const char *property_getName(objc_property_t property) +{ + return property->name; +}