
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@767 8e941d3f-bd1b-0410-a28a-d453659cc2b4
408 lines
18 KiB
ObjectPascal
408 lines
18 KiB
ObjectPascal
{
|
|
objcrtl.pas
|
|
|
|
Copyright (C) 2009 Dmitry Boyarintsev
|
|
|
|
This unit is a pascal binding for dynamic Objective-C Run-time Library
|
|
headers included with XCode 3.1.2
|
|
The original copyright note of is kept on each include file
|
|
}
|
|
unit objcrtl;
|
|
|
|
{$mode objfpc}{$H+}
|
|
|
|
interface
|
|
|
|
uses
|
|
dynlibs;
|
|
|
|
const
|
|
DefaultObjCLibName : AnsiString = 'libobjc.A.dylib';
|
|
|
|
|
|
{ Overview
|
|
--------
|
|
|
|
This document describes the Mac OS X Objective-C 2.0 runtime library support
|
|
functions and data structures. The functions are implemented in the shared
|
|
library found at /usr/lib/libobjc.A.dylib. This shared library provides support
|
|
for the dynamic properties of the Objective-C language, and as such is linked
|
|
to by all Objective-C applications.
|
|
|
|
This reference is useful primarily for developing bridge layers between
|
|
Objective-C and other languages, or for low-level debugging. You typically do
|
|
not need to use the Objective-C runtime library directly when programming
|
|
in Objective-C.
|
|
|
|
The Mac OS X implementation of the Objective-C runtime library is unique
|
|
to the Mac OS X platform. For other platforms, the GNU Compiler Collection
|
|
provides a different implementation with a similar API. This document covers
|
|
only the Mac OS X implementation.
|
|
|
|
The low-level Objective-C runtime API is significantly updated in Mac OS X
|
|
version 10.5. Many functions and all existing data structures are replaced
|
|
with new functions. The old functions and structures are deprecated in 32-bit
|
|
and absent in 64-bit mode. The API constrains several values to 32-bit ints
|
|
even in 64-bit mode—class count, protocol count, methods per class, ivars
|
|
per class, arguments per method, sizeof(all arguments) per method, and
|
|
class version number. In addition, the new Objective-C ABI (not described here)
|
|
further constrains sizeof(anInstance) to 32 bits, and three other values
|
|
to 24 bits—methods per class, ivars per class, and sizeof(a single ivar).
|
|
Finally, the obsolete NXHashTable and NXMapTable are limited to 4 billion items.
|
|
|
|
“Deprecated” below means “deprecated in Mac OS X version 10.5 for 32-bit code,
|
|
and disallowed for 64-bit code.
|
|
|
|
Legacy and Modern Versions
|
|
--------------------------
|
|
|
|
There are two versions of the Objective-C runtime—“modern” and “legacy”.
|
|
The modern version was introduced with Objective-C 2.0 and includes a number
|
|
of new features. The programming interface for the legacy version of the runtime
|
|
is described in Objective-C 1 Runtime Reference; the programming interface
|
|
for the modern version of the runtime is described in Objective-C 2.0 Runtime
|
|
Reference.
|
|
|
|
The most notable new feature is that instance variables in the modern runtime are “non-fragile”:
|
|
* In the legacy runtime, if you change the layout of instance variables in a class,
|
|
you must recompile classes that inherit from it.
|
|
* In the modern runtime, if you change the layout of instance variables in a class,
|
|
you do not have to recompile classes that inherit from it.
|
|
|
|
In addition, the modern runtime supports instance variable synthesis
|
|
for declared properties (see Declared Properties in The Objective-C 2.0 Programming Language).
|
|
|
|
Platforms
|
|
---------
|
|
|
|
iPhone applications and 64-bit programs on Mac OS X v10.5 and later use
|
|
the modern version of the runtime.
|
|
|
|
Other programs (32-bit programs on Mac OS X desktop) use the legacy version
|
|
of the runtime.
|
|
}
|
|
|
|
type
|
|
//todo: types MUST BE declared properly as 2.0 opaques
|
|
SEL = Pointer;
|
|
IMP = Pointer;
|
|
id = Pointer; //??
|
|
size_t = LongWord;
|
|
_Class = Pointer;
|
|
Ivar = Pointer;
|
|
PProtocol = Pointer;
|
|
PArrayPProtocol = Pointer;
|
|
BOOL = Boolean;
|
|
PIvar = Pointer;
|
|
Method = Pointer;
|
|
PMethod = Pointer;
|
|
Protocol = Pointer;
|
|
objc_property_t = Pointer;
|
|
Pobjc_property_t = Pointer;
|
|
uint8_t = byte;
|
|
Pobjc_method_description = Pointer;
|
|
ptrdiff_t = Pointer;
|
|
objc_method_description = Pointer;
|
|
TMutationHandlerProc = Pointer;
|
|
|
|
pobjc_super = ^objc_super;
|
|
objc_super = packed record
|
|
reciever : id;
|
|
class_ : _class;
|
|
end;
|
|
|
|
var
|
|
sel_getName : function (sel: SEL): PChar; cdecl = nil;
|
|
sel_registerName : function (str: PChar): SEL; cdecl = nil;
|
|
object_getClassName : function (obj: id): PChar; cdecl = nil;
|
|
object_getIndexedIvars : function (obj: id ): Pointer; cdecl = nil;
|
|
|
|
sel_isMapped: function (sel: SEL): Boolean; cdecl = nil;
|
|
sel_getUid: function (const str: PChar): SEL; cdecl = nil;
|
|
|
|
object_copy : function (obj:id; size:size_t):id; cdecl = nil;
|
|
object_dispose : function (obj:id):id; cdecl = nil;
|
|
|
|
object_getClass : function (obj:id): _Class; cdecl = nil;
|
|
object_setClass : function (obj:id; cls: _Class):_Class; cdecl = nil;
|
|
|
|
object_getIvar : function (obj:id; ivar:Ivar):id; cdecl = nil;
|
|
object_setIvar : procedure (obj:id; ivar:Ivar; value:id); cdecl = nil;
|
|
|
|
object_setInstanceVariable : function (obj:id; name:pchar; value:pointer):Ivar; cdecl = nil;
|
|
object_getInstanceVariable : function (obj:id; name:pchar; var outValue: Pointer):Ivar; cdecl = nil;
|
|
|
|
objc_getClass : function (name:pchar):id; cdecl = nil;
|
|
objc_getMetaClass : function (name:pchar):id; cdecl = nil;
|
|
objc_lookUpClass : function (name:pchar):id; cdecl = nil;
|
|
objc_getRequiredClass : function (name:pchar):id; cdecl = nil;
|
|
objc_getFutureClass : function (name:pchar):_Class; cdecl = nil;
|
|
objc_setFutureClass : procedure (cls:_Class; name:pchar); cdecl = nil;
|
|
objc_getClassList : function (buffer:pClass; bufferCount:longint):longint; cdecl = nil;
|
|
|
|
objc_getProtocol : function (name:pchar): PProtocol; cdecl = nil;
|
|
objc_copyProtocolList : function (outCount:pdword):PArrayPProtocol; cdecl = nil;
|
|
|
|
class_getName : function (cls:_Class):PChar; cdecl = nil;
|
|
class_isMetaClass : function (cls:_Class):BOOL; cdecl = nil;
|
|
class_getSuperclass : function (cls:_Class):_Class; cdecl = nil;
|
|
class_setSuperclass : function (cls: _Class; newSuper: _Class): _Class; cdecl = nil;
|
|
|
|
|
|
class_getVersion : function (cls:_Class):longint; cdecl = nil;
|
|
class_setVersion : procedure (cls:_Class; version:longint); cdecl = nil;
|
|
|
|
class_getInstanceSize : function (cls:_Class):size_t; cdecl = nil;
|
|
|
|
class_getInstanceVariable : function (cls:_Class; name:pchar):Ivar; cdecl = nil;
|
|
class_getClassVariable : function (cls:_Class; name:pchar):Ivar; cdecl = nil;
|
|
class_copyIvarList : function (cls:_Class; outCount:pdword):PIvar; cdecl = nil;
|
|
|
|
class_getInstanceMethod : function (cls:_Class; name:SEL):Method; cdecl = nil;
|
|
class_getClassMethod : function (cls:_Class; name:SEL):Method; cdecl = nil;
|
|
class_getMethodImplementation : function (cls:_Class; name:SEL):IMP; cdecl = nil;
|
|
class_getMethodImplementation_stret : function (cls:_Class; name:SEL):IMP; cdecl = nil;
|
|
class_respondsToSelector : function (cls:_Class; sel:SEL):BOOL; cdecl = nil;
|
|
class_copyMethodList : function (cls:_Class; outCount:pdword):PMethod; cdecl = nil;
|
|
|
|
class_conformsToProtocol : function (cls:_Class; var protocol: Protocol):BOOL; cdecl = nil;
|
|
class_copyProtocolList : function (cls:_Class; var outCount: dword):PArrayPProtocol; cdecl = nil;
|
|
|
|
class_getProperty : function (cls:_Class; name: pchar): objc_property_t; cdecl = nil;
|
|
class_copyPropertyList : function (cls:_Class; var Count:dword):Pobjc_property_t; cdecl = nil;
|
|
|
|
class_getIvarLayout : function (cls:_Class):Pchar; cdecl = nil;
|
|
class_getWeakIvarLayout : function (cls:_Class):Pchar; cdecl = nil;
|
|
|
|
class_createInstance : function (cls:_Class; extraBytes:size_t):id; cdecl = nil;
|
|
|
|
objc_allocateClassPair : function (superclass:_Class; name:pchar; extraBytes:size_t):_Class; cdecl = nil;
|
|
objc_registerClassPair : procedure (cls:_Class); cdecl = nil;
|
|
objc_duplicateClass : function (original:_Class; name:pchar; extraBytes:size_t):_Class; cdecl = nil;
|
|
objc_disposeClassPair : procedure (cls:_Class); cdecl = nil;
|
|
|
|
class_addMethod : function (cls:_Class; name:SEL; imp:IMP; types:pchar):BOOL; cdecl = nil;
|
|
class_replaceMethod : function (cls:_Class; name:SEL; imp:IMP; types:pchar):IMP; cdecl = nil;
|
|
class_addIvar: function (cls:_Class; name:pchar; size:size_t; alignment:uint8_t; types:pchar):BOOL; cdecl = nil;
|
|
class_addProtocol : function (cls:_Class; protocol:pProtocol):BOOL; cdecl = nil;
|
|
class_setIvarLayout : procedure (cls:_Class; layout:pchar); cdecl = nil;
|
|
class_setWeakIvarLayout : procedure (cls:_Class; layout:pchar); cdecl = nil;
|
|
|
|
method_getName : function (m:Method):SEL; cdecl = nil;
|
|
method_getImplementation : function (m:Method):IMP; cdecl = nil;
|
|
method_getTypeEncoding : function (m:Method):Pchar; cdecl = nil;
|
|
|
|
method_getNumberOfArguments : function (m:Method):dword; cdecl = nil;
|
|
method_copyReturnType : function (m:Method):Pchar; cdecl = nil;
|
|
method_copyArgumentType : function (m:Method; index:dword):Pchar; cdecl = nil;
|
|
method_getReturnType : procedure (m:Method; dst:pchar; dst_len:size_t); cdecl = nil;
|
|
method_getArgumentType : procedure (m:Method; index:dword; dst:pchar; dst_len:size_t); cdecl = nil;
|
|
method_getDescription : function (m: Method) : Pobjc_method_description; cdecl = nil;
|
|
|
|
method_setImplementation: function (m:Method; imp:IMP):IMP; cdecl = nil;
|
|
method_exchangeImplementations : procedure (m1:Method; m2:Method); cdecl = nil;
|
|
|
|
ivar_getName : function (v:Ivar):Pchar; cdecl = nil;
|
|
ivar_getTypeEncoding : function (v:Ivar):Pchar; cdecl = nil;
|
|
ivar_getOffset : function (v:Ivar):ptrdiff_t; cdecl = nil;
|
|
|
|
property_getName :function (_property:objc_property_t):Pchar; cdecl = nil;
|
|
property_getAttributes : function (_property:objc_property_t):Pchar; cdecl = nil;
|
|
|
|
|
|
protocol_conformsToProtocol : function (proto:pProtocol; other:pProtocol):BOOL; cdecl = nil;
|
|
protocol_isEqual : function (proto:pProtocol; other:pProtocol):BOOL; cdecl = nil;
|
|
protocol_getMethodDescription : function (p: PProtocol; aSel: SEL; isRequiredMethod, isInstanceMethod: BOOL): objc_method_description; cdecl = nil;
|
|
protocol_copyMethodDescriptionList : function (p: PProtocol; isRequiredMethod, isInstanceMethod: BOOL ; var outCount: LongWord): Pobjc_method_description; cdecl = nil;
|
|
protocol_getProperty : function (proto:PProtocol; name:pchar; isRequiredProperty:BOOL; isInstanceProperty:BOOL):objc_property_t; cdecl = nil;
|
|
protocol_copyPropertyList : function (proto:PProtocol; outCount:pdword):Pobjc_property_t; cdecl = nil;
|
|
protocol_copyProtocolList : function (proto:PProtocol; outCount:pdword):PArrayPProtocol; cdecl = nil;
|
|
|
|
objc_copyImageNames : function (var outCount:dword): PPchar; cdecl = nil;
|
|
class_getImageName : function (cls:_Class):Pchar; cdecl = nil;
|
|
objc_copyClassNamesForImage : function (image:pchar; var outCount: Dword):PPchar; cdecl = nil;
|
|
|
|
sel_isEqual : function (lhs:SEL; rhs:SEL):BOOL; cdecl = nil;
|
|
objc_enumerationMutation : procedure (_para1:id); cdecl = nil;
|
|
objc_setEnumerationMutationHandler : procedure (handler:TMutationHandlerProc); cdecl = nil;
|
|
objc_setForwardHandler: procedure (fwd:pointer; fwd_stret:pointer); cdecl = nil;
|
|
|
|
{$WARNINGS OFF} // warning: cdecl'ared funtions have no high parameter
|
|
objc_msgSend : function (self: id; op: SEL; param3: array of const): id; cdecl = nil;
|
|
objc_msgSendSuper : function (super: pobjc_super; op: SEL; param3: array of const): id; cdecl = nil;
|
|
objc_msgSend_stret : procedure (stret: Pointer; self: id; op: SEL; param3: array of const); cdecl= nil;
|
|
objc_msgSend_stretreg : function (self: id; op: SEL; param3: array of const): id; cdecl= nil;
|
|
objc_msgSendSuper_stret : procedure (stret: Pointer; super: pobjc_super; op: SEL; param3: array of const); cdecl = nil;
|
|
objc_msgSend_fpret : function (self: id; op: SEL; param3: array of const): double; cdecl = nil;
|
|
{$WARNINGS ON}
|
|
|
|
method_invoke : function (receiver: id; m: Method {, ...}): id= nil;
|
|
method_invoke_stret : procedure (receiver: id; m: Method{ , ...})= nil;
|
|
objc_collect : procedure (options: LongWord); cdecl= nil;
|
|
objc_collectingEnabled : function : BOOL; cdecl= nil;
|
|
|
|
const
|
|
_C_ID = '@';
|
|
_C_CLASS = '#';
|
|
_C_SEL = ':';
|
|
_C_CHR = 'c';
|
|
_C_UCHR = 'C';
|
|
_C_SHT = 's';
|
|
_C_USHT = 'S';
|
|
_C_INT = 'i';
|
|
_C_UINT = 'I';
|
|
_C_LNG = 'l';
|
|
_C_ULNG = 'L';
|
|
_C_FLT = 'f';
|
|
_C_DBL = 'd';
|
|
_C_BFLD = 'b';
|
|
_C_VOID = 'v';
|
|
_C_UNDEF = '?';
|
|
_C_PTR = '^';
|
|
_C_CHARPTR = '*';
|
|
_C_ARY_B = '[';
|
|
_C_ARY_E = ']';
|
|
_C_UNION_B = '(';
|
|
_C_UNION_E = ')';
|
|
_C_STRUCT_B = '{';
|
|
_C_STRUCT_E = '}';
|
|
_C_PASOBJ = _C_PTR + _C_VOID;
|
|
_C_SELF_AND_SEL = '@:';
|
|
|
|
// objc-exception.h
|
|
|
|
// compiler reserves a setjmp buffer + 4 words as localExceptionData
|
|
|
|
type
|
|
Tobjc_exception_throw = procedure (exception: id); cdecl;
|
|
Tobjc_exception_try_enter = procedure (localExceptionData: Pointer); cdecl;
|
|
Tobjc_exception_try_exit = procedure (localExceptionData: Pointer); cdecl;
|
|
Tobjc_exception_extract = function (localExceptionData: Pointer): id; cdecl;
|
|
Tobjc_exception_match = function (exceptionClass:_Class; exception:id ): Integer; cdecl;
|
|
|
|
var
|
|
objc_exception_throw : Tobjc_exception_throw = nil;
|
|
objc_exception_try_enter : Tobjc_exception_try_enter = nil;
|
|
objc_exception_try_exit : Tobjc_exception_try_exit = nil;
|
|
objc_exception_extract : Tobjc_exception_extract = nil;
|
|
objc_exception_match : Tobjc_exception_match = nil;
|
|
|
|
type
|
|
pobjc_exception_functions_t = ^objc_exception_functions_t;
|
|
objc_exception_functions_t = packed record
|
|
version : Integer;
|
|
throw_exc : Tobjc_exception_throw; // version 0
|
|
try_enter : Tobjc_exception_try_enter; // version 0
|
|
try_exit : Tobjc_exception_try_exit; // version 0
|
|
extract : Tobjc_exception_extract; // version 0
|
|
match : Tobjc_exception_match; // version 0
|
|
end;
|
|
|
|
// get table; version tells how many
|
|
var
|
|
objc_exception_get_functions : procedure (var table: objc_exception_functions_t); cdecl = nil;
|
|
objc_exception_set_functions : procedure (table: pobjc_exception_functions_t); cdecl = nil;
|
|
|
|
|
|
// __LP64__ // 64-bit only functions
|
|
{
|
|
typedef id (*objc_exception_preprocessor)(id exception);
|
|
typedef int (*objc_exception_matcher)(Class catch_type, id exception);
|
|
typedef void (*objc_uncaught_exception_handler)(id exception);
|
|
typedef void (*objc_exception_handler)(id unused, void *context);
|
|
|
|
OBJC_EXPORT void objc_exception_throw(id exception);
|
|
OBJC_EXPORT void objc_exception_rethrow(void);
|
|
OBJC_EXPORT id objc_begin_catch(void *exc_buf);
|
|
OBJC_EXPORT void objc_end_catch(void);
|
|
|
|
OBJC_EXPORT uintptr_t objc_addExceptionHandler(objc_exception_handler fn, void *context);
|
|
OBJC_EXPORT void objc_removeExceptionHandler(uintptr_t token);
|
|
|
|
OBJC_EXPORT objc_exception_preprocessor objc_setExceptionPreprocessor(objc_exception_preprocessor fn);
|
|
OBJC_EXPORT objc_exception_matcher objc_setExceptionMatcher(objc_exception_matcher fn);
|
|
OBJC_EXPORT objc_uncaught_exception_handler objc_setUncaughtExceptionHandler(objc_uncaught_exception_handler fn);
|
|
}
|
|
|
|
|
|
|
|
// objc-sync.h
|
|
|
|
var
|
|
// Begin synchronizing on 'obj'.
|
|
// Allocates recursive pthread_mutex associated with 'obj' if needed.
|
|
// Returns OBJC_SYNC_SUCCESS once lock is acquired.
|
|
objc_sync_enter: function (obj: id): Integer; cdecl = nil;
|
|
// End synchronizing on 'obj'.
|
|
// Returns OBJC_SYNC_SUCCESS or OBJC_SYNC_NOT_OWNING_THREAD_ERROR
|
|
objc_sync_exit : function (obj: id) : Integer; cdecl = nil;
|
|
// Temporarily release lock on 'obj' and wait for another thread to notify on 'obj'
|
|
// Return OBJC_SYNC_SUCCESS, OBJC_SYNC_NOT_OWNING_THREAD_ERROR, OBJC_SYNC_TIMED_OUT
|
|
objc_sync_wait : function (obj: id; milliSecondsMaxWait: Int64): Integer; cdecl = nil;
|
|
// Wake up another thread waiting on 'obj'
|
|
// Return OBJC_SYNC_SUCCESS, OBJC_SYNC_NOT_OWNING_THREAD_ERROR
|
|
objc_sync_notify : function (obj: id): Integer; cdecl = nil;
|
|
// Wake up all threads waiting on 'obj'
|
|
// Return OBJC_SYNC_SUCCESS, OBJC_SYNC_NOT_OWNING_THREAD_ERROR
|
|
objc_sync_notifyAll : function (obj: id): Integer; cdecl = nil;
|
|
|
|
const
|
|
OBJC_SYNC_SUCCESS = 0;
|
|
OBJC_SYNC_NOT_OWNING_THREAD_ERROR = -1;
|
|
OBJC_SYNC_TIMED_OUT = -2;
|
|
OBJC_SYNC_NOT_INITIALIZED = -3;
|
|
|
|
// since exception handling does not change from version to version
|
|
// it's nice to make a common RTL loading function for exception functions.
|
|
// this proc, MUST BE called by run-time initialization proc!
|
|
function LoadDefaultObjCExepction(hnd: TLibHandle): Boolean;
|
|
function LoadDefaultObjCSync(hnd: TLibHandle): Boolean;
|
|
function LoadDefaultObjCMessaging(hnd: TLibHandle): Boolean;
|
|
|
|
implementation
|
|
|
|
function LoadDefaultObjCExepction(hnd: TLibHandle): Boolean;
|
|
begin
|
|
Result := hnd <> 0;
|
|
if not Result then Exit;
|
|
|
|
objc_exception_throw := Tobjc_exception_throw(GetProcedureAddress(hnd, 'objc_exception_throw'));
|
|
objc_exception_try_enter := Tobjc_exception_try_enter(GetProcedureAddress(hnd, 'objc_exception_try_enter'));
|
|
objc_exception_try_exit := Tobjc_exception_try_exit(GetProcedureAddress(hnd, 'objc_exception_try_exit'));
|
|
objc_exception_extract := Tobjc_exception_extract(GetProcedureAddress(hnd, 'objc_exception_extract'));
|
|
objc_exception_match := Tobjc_exception_match(GetProcedureAddress(hnd, 'objc_exception_match'));
|
|
end;
|
|
|
|
function LoadDefaultObjCSync(hnd: TLibHandle): Boolean;
|
|
begin
|
|
Result := hnd <> 0;
|
|
if not Result then Exit;
|
|
Pointer(objc_sync_enter) := GetProcedureAddress(hnd, 'objc_sync_enter');
|
|
Pointer(objc_sync_exit) := GetProcedureAddress(hnd, 'objc_sync_exit');
|
|
Pointer(objc_sync_wait) := GetProcedureAddress(hnd, 'objc_sync_wait');
|
|
Pointer(objc_sync_notify) := GetProcedureAddress(hnd, 'objc_sync_notify');
|
|
Pointer(objc_sync_notifyAll) := GetProcedureAddress(hnd, 'objc_sync_notifyAll');
|
|
end;
|
|
|
|
function LoadDefaultObjCMessaging(hnd: TLibHandle): Boolean;
|
|
begin
|
|
Pointer(objc_msgSend) := GetProcedureAddress(hnd, 'objc_msgSend');
|
|
Pointer(objc_msgSendSuper) := GetProcedureAddress(hnd, 'objc_msgSendSuper');
|
|
Pointer(objc_msgSend_stret) := GetProcedureAddress(hnd, 'objc_msgSend_stret');
|
|
Pointer(objc_msgSendSuper_stret) := GetProcedureAddress(hnd, 'objc_msgSendSuper_stret');
|
|
|
|
{$ifndef CPUPOWERPC} // arm also uses objc_msgSend_fpret?
|
|
Pointer(objc_msgSend_fpret) := GetProcedureAddress(hnd, 'objc_msgSend_fpret');
|
|
Pointer(objc_msgSend_stretreg) := GetProcedureAddress(hnd, 'objc_msgSend');
|
|
{$else}
|
|
Pointer(objc_msgSend_fpret) := GetProcedureAddress(hnd, 'objc_msgSend');
|
|
Pointer(objc_msgSend_stretreg) := GetProcedureAddress(hnd, 'objc_msgSend_stret');
|
|
{$endif}
|
|
Result := true;
|
|
end;
|
|
|
|
initialization
|
|
|
|
end.
|
|
|