You've already forked lazarus-ccr
added: _stretreg funcion; 1.0 ivariables binding; missing type encoding constants; common objc_msgSend* loading
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@760 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
@ -231,6 +231,7 @@ var
|
|||||||
objc_msgSend : function (self: id; op: SEL; param3: array of const): id; cdecl = nil;
|
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_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_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_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;
|
objc_msgSend_fpret : function (self: id; op: SEL; param3: array of const): double; cdecl = nil;
|
||||||
{$WARNINGS ON}
|
{$WARNINGS ON}
|
||||||
@ -240,6 +241,34 @@ var
|
|||||||
objc_collect : procedure (options: LongWord); cdecl= nil;
|
objc_collect : procedure (options: LongWord); cdecl= nil;
|
||||||
objc_collectingEnabled : function : BOOL; 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
|
// objc-exception.h
|
||||||
|
|
||||||
// compiler reserves a setjmp buffer + 4 words as localExceptionData
|
// compiler reserves a setjmp buffer + 4 words as localExceptionData
|
||||||
@ -296,10 +325,6 @@ OBJC_EXPORT objc_uncaught_exception_handler objc_setUncaughtExceptionHandler(obj
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// 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;
|
|
||||||
|
|
||||||
// objc-sync.h
|
// objc-sync.h
|
||||||
|
|
||||||
@ -307,7 +332,7 @@ var
|
|||||||
// Begin synchronizing on 'obj'.
|
// Begin synchronizing on 'obj'.
|
||||||
// Allocates recursive pthread_mutex associated with 'obj' if needed.
|
// Allocates recursive pthread_mutex associated with 'obj' if needed.
|
||||||
// Returns OBJC_SYNC_SUCCESS once lock is acquired.
|
// Returns OBJC_SYNC_SUCCESS once lock is acquired.
|
||||||
objc_sync_enter: function (obj: id ): Integer; cdecl = nil;
|
objc_sync_enter: function (obj: id): Integer; cdecl = nil;
|
||||||
// End synchronizing on 'obj'.
|
// End synchronizing on 'obj'.
|
||||||
// Returns OBJC_SYNC_SUCCESS or OBJC_SYNC_NOT_OWNING_THREAD_ERROR
|
// Returns OBJC_SYNC_SUCCESS or OBJC_SYNC_NOT_OWNING_THREAD_ERROR
|
||||||
objc_sync_exit : function (obj: id) : Integer; cdecl = nil;
|
objc_sync_exit : function (obj: id) : Integer; cdecl = nil;
|
||||||
@ -327,7 +352,12 @@ const
|
|||||||
OBJC_SYNC_TIMED_OUT = -2;
|
OBJC_SYNC_TIMED_OUT = -2;
|
||||||
OBJC_SYNC_NOT_INITIALIZED = -3;
|
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 LoadDefaultObjCSync(hnd: TLibHandle): Boolean;
|
||||||
|
function LoadDefaultObjCMessaging(hnd: TLibHandle): Boolean;
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
@ -336,8 +366,8 @@ begin
|
|||||||
Result := hnd <> 0;
|
Result := hnd <> 0;
|
||||||
if not Result then Exit;
|
if not Result then Exit;
|
||||||
|
|
||||||
objc_exception_throw := Tobjc_exception_throw( GetProcedureAddress(hnd, 'objc_exception_throw'));
|
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_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_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_extract := Tobjc_exception_extract(GetProcedureAddress(hnd, 'objc_exception_extract'));
|
||||||
objc_exception_match := Tobjc_exception_match(GetProcedureAddress(hnd, 'objc_exception_match'));
|
objc_exception_match := Tobjc_exception_match(GetProcedureAddress(hnd, 'objc_exception_match'));
|
||||||
@ -354,6 +384,22 @@ begin
|
|||||||
Pointer(objc_sync_notifyAll) := GetProcedureAddress(hnd, 'objc_sync_notifyAll');
|
Pointer(objc_sync_notifyAll) := GetProcedureAddress(hnd, 'objc_sync_notifyAll');
|
||||||
end;
|
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_streg');
|
||||||
|
{$endif}
|
||||||
|
end;
|
||||||
|
|
||||||
initialization
|
initialization
|
||||||
|
|
||||||
end.
|
end.
|
||||||
|
@ -31,11 +31,35 @@ uses
|
|||||||
http://developer.apple.com/documentation/Cocoa/Reference/ObjCRuntimeRef/Articles/ocr10_5delta.html#//apple_ref/doc/uid/TP40002981-TPXREF101
|
http://developer.apple.com/documentation/Cocoa/Reference/ObjCRuntimeRef/Articles/ocr10_5delta.html#//apple_ref/doc/uid/TP40002981-TPXREF101
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function InitializeObjCRtl10(const ObjCLibName: AnsiString): Boolean;
|
function InitializeObjCRtl10(const ObjCLibName: AnsiString): Boolean;
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
|
{$HINTS OFF} {.Parameter not used.}
|
||||||
|
|
||||||
|
function ObjCAllocMem(size: Integer): Pointer;
|
||||||
|
begin
|
||||||
|
//todo: store the mem pointers
|
||||||
|
// and release them at finalization section
|
||||||
|
// this must be thread safe, so allocating additional NsObject
|
||||||
|
// that can be used with objc_sync is recommended
|
||||||
|
Result := AllocMem(size);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure ObjCFreeMem(p: Pointer);
|
||||||
|
begin
|
||||||
|
//todo:
|
||||||
|
Freemem(p);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
function allocstr(const src: String): Pchar;
|
||||||
|
begin
|
||||||
|
Result := ObjCAllocMem(length(src)+1);
|
||||||
|
if src <> '' then System.Move(src[1], Result^, length(src));
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
const
|
const
|
||||||
CLS_CLASS = $1;
|
CLS_CLASS = $1;
|
||||||
CLS_META = $2;
|
CLS_META = $2;
|
||||||
@ -198,53 +222,102 @@ var
|
|||||||
//class_addMethods : procedure (myClass: _Class1; methodList : Pobjc_method_list1); cdecl;
|
//class_addMethods : procedure (myClass: _Class1; methodList : Pobjc_method_list1); cdecl;
|
||||||
|
|
||||||
type
|
type
|
||||||
TClassMethod1Reg = record
|
|
||||||
listpointer : Pobjc_method_list1;
|
{ TClassMethod1Reg }
|
||||||
itemscount : Integer;
|
|
||||||
|
TClassMethod1Reg = class(TObject)
|
||||||
|
private
|
||||||
|
methods : array of objc_method1;
|
||||||
|
count : Integer;
|
||||||
|
public
|
||||||
|
procedure AddMethod(name:SEL; imp:IMP; types:pchar);
|
||||||
|
function AllocMethodList: Pobjc_method_list1;
|
||||||
end;
|
end;
|
||||||
PClassMethod1Reg = ^TClassMethod1Reg;
|
//PClassMethod1Reg = ^TClassMethod1Reg;
|
||||||
|
|
||||||
function AllocMethodReg: PClassMethod1Reg;
|
TIVar1Reg = record
|
||||||
begin
|
size : Integer;
|
||||||
Result := GetMem(sizeof (TClassMethod1Reg));
|
types : String;
|
||||||
Result^.itemscount := 0;
|
name : String;
|
||||||
Result^.listpointer := Pointer(-1);
|
alignment : Uint8_t;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function ReleaseMethodReg(p : PClassMethod1Reg): PPobjc_method_list1;
|
{ TClassIVar1Reg }
|
||||||
begin
|
|
||||||
Result := GetMem(sizeof(Pobjc_method_list1));
|
|
||||||
if p^.itemscount = 0
|
|
||||||
then Result^ := Pointer(-1)
|
|
||||||
else Result^ := p^.listpointer;
|
|
||||||
Freemem(p);
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure AddMethodToList(var list: TClassMethod1Reg; name:SEL; imp:IMP; types:pchar);
|
TClassIVar1Reg = class(TObject)
|
||||||
var
|
private
|
||||||
n : Integer;
|
ivarscount : Integer;
|
||||||
sz : Integer;
|
ivars : array of TIVar1Reg;
|
||||||
nlist : Pobjc_method_list1;
|
public
|
||||||
|
procedure AddIVar(name:pchar; size:size_t; alignment:uint8_t; types:pchar);
|
||||||
|
function AllocIVarsList(ivarOffset: Integer; out ivarssize: Integer): Pobjc_ivar_list1;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TClassMethod1Reg }
|
||||||
|
|
||||||
|
procedure TClassMethod1Reg.AddMethod(name: SEL; imp: IMP; types: pchar);
|
||||||
begin
|
begin
|
||||||
if list.itemscount = 0 then begin
|
if length(methods) = count then begin
|
||||||
list.listpointer := GetMem(sizeof(objc_method_list1));
|
if count = 0 then SetLength(methods, 4)
|
||||||
list.listpointer^.method_count := 1;
|
else begin
|
||||||
list.itemscount := 1;
|
SetLength(methods, count * 2);
|
||||||
n := 0;
|
end;
|
||||||
end else begin
|
end;
|
||||||
if list.listpointer^.method_count = list.itemscount then begin
|
methods[count].method_imp := IMP1(imp);
|
||||||
list.itemscount := list.itemscount * 2;
|
methods[count].method_types := allocstr(types);
|
||||||
sz := sizeof(objc_method_list1) + ((list.itemscount) - 1) * sizeof(objc_method1);
|
methods[count].method_name := name;
|
||||||
nlist := GetMem(sz);
|
inc(count);
|
||||||
sz := sizeof(objc_method_list1) + ((list.listpointer^.method_count) - 1) * sizeof(objc_method1);
|
end;
|
||||||
System.Move(list.listpointer^, nlist^, sizeof(objc_method_list1) + ((list.itemscount) - 1) * sizeof(objc_method1));
|
|
||||||
|
function TClassMethod1Reg.AllocMethodList: Pobjc_method_list1;
|
||||||
|
var
|
||||||
|
i : Integer;
|
||||||
|
begin
|
||||||
|
if count = 0 then Result := nil
|
||||||
|
else begin
|
||||||
|
Result := ObjCAllocMem( sizeof(objc_method_list1) + (count-1)*sizeof(objc_method1) );
|
||||||
|
Pobjc_method_list1(Result)^.method_count := count;
|
||||||
|
for i := 0 to count - 1 do begin
|
||||||
|
Pobjc_method_list1(Result)^.method_list1[i].method_name := methods[i].method_name;
|
||||||
|
Pobjc_method_list1(Result)^.method_list1[i].method_types := methods[i].method_types;
|
||||||
|
Pobjc_method_list1(Result)^.method_list1[i].method_imp := methods[i].method_imp;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TClassIVar1Reg.AddIVar(name: pchar; size: size_t; alignment: uint8_t;
|
||||||
|
types: pchar);
|
||||||
|
begin
|
||||||
|
if ivarscount = length(ivars) then begin
|
||||||
|
if ivarscount = 0 then SetLength(ivars, 4)
|
||||||
|
else setLength(ivars, ivarscount * 2);
|
||||||
|
end;
|
||||||
|
ivars[ivarscount].name := name;
|
||||||
|
ivars[ivarscount].size := size;
|
||||||
|
ivars[ivarscount].types := types;
|
||||||
|
ivars[ivarscount].alignment := alignment;
|
||||||
|
inc(ivarscount);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TClassIVar1Reg.AllocIVarsList(ivarOffset: Integer; out ivarssize: Integer): Pobjc_ivar_list1;
|
||||||
|
var
|
||||||
|
i : Integer;
|
||||||
|
|
||||||
|
begin
|
||||||
|
if ivarscount = 0 then begin
|
||||||
|
Result := nil;
|
||||||
|
ivarssize := 0;
|
||||||
|
end else begin
|
||||||
|
ivarssize := 0;
|
||||||
|
Result := ObjCAllocMem( sizeof(objc_ivar_list1) + (ivarscount-1)*sizeof(objc_ivar1) );
|
||||||
|
Result^.ivar_count := ivarscount;
|
||||||
|
for i := 0 to ivarscount - 1 do begin
|
||||||
|
Result^.ivar_list[i].ivar_name := allocstr(ivars[i].name);
|
||||||
|
Result^.ivar_list[i].ivar_offset := ivarOffset + ivarssize;
|
||||||
|
Result^.ivar_list[i].ivar_type := allocstr(ivars[i].name);
|
||||||
|
inc(ivarssize, ivars[i].size);
|
||||||
end;
|
end;
|
||||||
n := list.listpointer^.method_count;
|
|
||||||
inc(list.listpointer^.method_count);
|
|
||||||
end;
|
end;
|
||||||
list.listpointer^.method_list1[n].method_types := types;
|
|
||||||
list.listpointer^.method_list1[n].method_imp := IMP1(imp);
|
|
||||||
list.listpointer^.method_list1[n].method_name := SEL1(name);
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function object_getClass10(obj:id): _Class; cdecl;
|
function object_getClass10(obj:id): _Class; cdecl;
|
||||||
@ -341,7 +414,7 @@ begin
|
|||||||
root_class := root_class^.super_class;
|
root_class := root_class^.super_class;
|
||||||
|
|
||||||
// Allocate space for the class and its metaclass
|
// Allocate space for the class and its metaclass
|
||||||
new_class := AllocMem(2 * SizeOf(objc_class1));
|
new_class := ObjCAllocMem(2 * SizeOf(objc_class1));
|
||||||
meta_class := @new_class[1];
|
meta_class := @new_class[1];
|
||||||
|
|
||||||
// setup class
|
// setup class
|
||||||
@ -354,14 +427,14 @@ begin
|
|||||||
// to share this copy of the name, but this is not a requirement
|
// to share this copy of the name, but this is not a requirement
|
||||||
// imposed by the runtime.
|
// imposed by the runtime.
|
||||||
namelen := strlen(name);
|
namelen := strlen(name);
|
||||||
new_class^.name := AllocMem(namelen + 1);
|
new_class^.name := ObjCAllocMem(namelen + 1);
|
||||||
Move(name^, new_class^.name^, namelen);
|
Move(name^, new_class^.name^, namelen);
|
||||||
meta_class^.name := new_class^.name;
|
meta_class^.name := new_class^.name;
|
||||||
|
|
||||||
// Allocate empty method lists.
|
// Allocate empty method lists.
|
||||||
// We can add methods later.
|
// We can add methods later.
|
||||||
new_class^.methodLists := PPObjc_method_list1(AllocMethodReg); //AllocMem ( SizeOf(TClassMethod1Reg)) ;// SizeOf(Pobjc_method_list1));
|
new_class^.methodLists := Pointer(TClassMethod1Reg.Create); // PPObjc_method_list1(AllocMethodReg); //AllocMem ( SizeOf(TClassMethod1Reg)) ;// SizeOf(Pobjc_method_list1));
|
||||||
meta_class^.methodLists := PPObjc_method_list1(AllocMethodReg);
|
meta_class^.methodLists := Pointer(TClassMethod1Reg.Create); //PPObjc_method_list1(AllocMethodReg);
|
||||||
|
|
||||||
// Connect the class definition to the class hierarchy:
|
// Connect the class definition to the class hierarchy:
|
||||||
// Connect the class to the superclass.
|
// Connect the class to the superclass.
|
||||||
@ -374,6 +447,7 @@ begin
|
|||||||
// Set the sizes of the class and the metaclass.
|
// Set the sizes of the class and the metaclass.
|
||||||
new_class^.instance_size := super^.instance_size;
|
new_class^.instance_size := super^.instance_size;
|
||||||
meta_class^.instance_size := meta_class^.super_class^.instance_size;
|
meta_class^.instance_size := meta_class^.super_class^.instance_size;
|
||||||
|
new_class^.ivars := Pointer(TClassIVar1Reg.Create);
|
||||||
|
|
||||||
Result := new_class;
|
Result := new_class;
|
||||||
end;
|
end;
|
||||||
@ -382,15 +456,46 @@ procedure objc_registerClassPair10(aClass:_Class); cdecl;
|
|||||||
var
|
var
|
||||||
meta_class : _Class1;
|
meta_class : _Class1;
|
||||||
new_class : _Class1;
|
new_class : _Class1;
|
||||||
|
|
||||||
|
MethodReg : TClassMethod1Reg;
|
||||||
|
|
||||||
|
iVarReg : TClassIVar1Reg;
|
||||||
|
ivarslist : Pobjc_ivar_list1;
|
||||||
|
sz : Integer;
|
||||||
|
|
||||||
|
procedure RegisterMethodList(reg: TClassMethod1Reg; cls1: _Class1);
|
||||||
|
var
|
||||||
|
mtdlist : Pobjc_method_list1;
|
||||||
|
begin
|
||||||
|
if not Assigned(reg) then Exit;
|
||||||
|
cls1^.methodLists := ObjCAllocMem(sizeof(Pobjc_method_list1));
|
||||||
|
mtdList := reg.AllocMethodList;
|
||||||
|
if not Assigned(mtdlist)
|
||||||
|
then cls1^.methodLists^ := Pointer(-1)
|
||||||
|
else cls1^.methodLists^ := mtdlist;
|
||||||
|
end;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
new_class := _Class1(aClass);
|
new_class := _Class1(aClass);
|
||||||
// Finally, register the class with the runtime.
|
|
||||||
new_class^.methodLists := ReleaseMethodReg(PClassMethod1Reg(new_class^.methodLists));
|
|
||||||
meta_class := _Class1(new_Class)^.isa;
|
meta_class := _Class1(new_Class)^.isa;
|
||||||
meta_class^.methodLists := ReleaseMethodReg(PClassMethod1Reg(meta_class^.methodLists));
|
// Finally, register the class with the runtime.
|
||||||
|
|
||||||
if new_class <> nil then
|
MethodReg := TClassMethod1Reg(new_class^.methodLists);
|
||||||
objc_addClass(new_class);
|
RegisterMethodList(MethodReg, new_class);
|
||||||
|
MethodReg.Free;
|
||||||
|
|
||||||
|
MethodReg := TClassMethod1Reg(meta_class^.methodLists);
|
||||||
|
RegisterMethodList(MethodReg, meta_class);
|
||||||
|
MethodReg.Free;
|
||||||
|
|
||||||
|
iVarReg := TClassIVar1Reg(new_class^.ivars);
|
||||||
|
ivarslist := iVarReg.AllocIVarsList(new_class^.instance_size, sz);
|
||||||
|
new_class^.ivars := ivarslist;
|
||||||
|
inc(new_class^.instance_size, sz);
|
||||||
|
iVarReg.Free;
|
||||||
|
|
||||||
|
|
||||||
|
if new_class <> nil then objc_addClass(new_class);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function objc_duplicateClass10(original:_Class; name:pchar; extraBytes:size_t):_Class; cdecl;
|
function objc_duplicateClass10(original:_Class; name:pchar; extraBytes:size_t):_Class; cdecl;
|
||||||
@ -403,26 +508,27 @@ begin
|
|||||||
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function class_addMethod10(cls:_Class; name:SEL; imp:IMP; types:pchar):BOOL; cdecl;
|
function class_addMethod10(cls:_Class; name:SEL; _imp:IMP; types:pchar):BOOL; cdecl;
|
||||||
var
|
|
||||||
//list : Pobjc_method_list1;
|
|
||||||
reg : PClassMethod1Reg;
|
|
||||||
begin
|
begin
|
||||||
reg := PClassMethod1Reg(_Class1(cls)^.methodLists);
|
if not Assigned(cls) or not Assigned(name) or not Assigned(_imp) or not Assigned(types) then begin
|
||||||
AddMethodToList( reg^, name, imp, types);
|
Result := false;
|
||||||
|
Exit;
|
||||||
{ list := GetMem(sizeof(objc_method_list1));
|
end;
|
||||||
list^.method_count := 1;
|
TClassMethod1Reg(_Class1(cls)^.methodLists).AddMethod(name, _imp, types);
|
||||||
list^.method_list1[0].method_imp := IMP1(imp);
|
|
||||||
list^.method_list1[0].method_name := SEL1(name);
|
|
||||||
list^.method_list1[0].method_types := types;
|
|
||||||
class_addMethods(cls, @list);}
|
|
||||||
Result := true;
|
Result := true;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function class_addIvar10(cls:_Class; name:pchar; size:size_t; alignment:uint8_t; types:pchar):BOOL; cdecl;
|
function class_addIvar10(cls:_Class; name:pchar; size:size_t; alignment:uint8_t; types:pchar):BOOL; cdecl;
|
||||||
|
var
|
||||||
|
cls1 : _Class1;
|
||||||
begin
|
begin
|
||||||
Result := false;
|
if (alignment <> 1) or (class_isMetaClass10(cls)) then begin
|
||||||
|
Result := false;
|
||||||
|
Exit;
|
||||||
|
end;
|
||||||
|
cls1 := _Class1(cls);
|
||||||
|
TClassIVar1Reg(cls1^.ivars).AddIVar(name, size, alignment, types);
|
||||||
|
Result := true;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function class_addProtocol10(cls:_Class; protocol:pProtocol):BOOL; cdecl;
|
function class_addProtocol10(cls:_Class; protocol:pProtocol):BOOL; cdecl;
|
||||||
@ -670,17 +776,8 @@ begin
|
|||||||
|
|
||||||
|
|
||||||
//Messaging
|
//Messaging
|
||||||
//The following functions are unchanged:
|
LoadDefaultObjCMessaging(hnd);
|
||||||
Pointer(objc_msgSend) := GetProcedureAddress(hnd, 'objc_msgSend');
|
|
||||||
Pointer(objc_msgSend_stret) := GetProcedureAddress(hnd, 'objc_msgSend_stret');
|
|
||||||
Pointer(objc_msgSendSuper) := GetProcedureAddress(hnd, 'objc_msgSendSuper');
|
|
||||||
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');
|
|
||||||
{$else}
|
|
||||||
Pointer(objc_msgSend_fpret) := GetProcedureAddress(hnd, 'objc_msgSend');
|
|
||||||
{$endif}
|
|
||||||
|
|
||||||
//The following functions are removed:objc_msgSendv Given an argument list, send a message with a simple return value.
|
//The following functions are removed:objc_msgSendv Given an argument list, send a message with a simple return value.
|
||||||
//objc_msgSendv_stret Given an argument list, send a message with a data-structure return value.
|
//objc_msgSendv_stret Given an argument list, send a message with a data-structure return value.
|
||||||
|
@ -145,16 +145,8 @@ begin
|
|||||||
Pointer(objc_setEnumerationMutationHandler) := GetProcedureAddress(hnd, 'objc_setEnumerationMutationHandler');
|
Pointer(objc_setEnumerationMutationHandler) := GetProcedureAddress(hnd, 'objc_setEnumerationMutationHandler');
|
||||||
Pointer(objc_setForwardHandler) := GetProcedureAddress(hnd, 'objc_setForwardHandler');
|
Pointer(objc_setForwardHandler) := GetProcedureAddress(hnd, 'objc_setForwardHandler');
|
||||||
|
|
||||||
Pointer(objc_msgSend) := GetProcedureAddress(hnd, 'objc_msgSend');
|
//Messaging
|
||||||
Pointer(objc_msgSendSuper) := GetProcedureAddress(hnd, 'objc_msgSendSuper');
|
LoadDefaultObjCMessaging(hnd);
|
||||||
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');
|
|
||||||
{$else}
|
|
||||||
Pointer(objc_msgSend_fpret) := GetProcedureAddress(hnd, 'objc_msgSend');
|
|
||||||
{$endif}
|
|
||||||
|
|
||||||
Pointer(method_invoke) := GetProcedureAddress(hnd, 'method_invoke');
|
Pointer(method_invoke) := GetProcedureAddress(hnd, 'method_invoke');
|
||||||
Pointer(method_invoke_stret) := GetProcedureAddress(hnd, 'method_invoke_stret');
|
Pointer(method_invoke_stret) := GetProcedureAddress(hnd, 'method_invoke_stret');
|
||||||
|
@ -27,7 +27,8 @@ type
|
|||||||
PSmallRecord = ^TSmallRecord;
|
PSmallRecord = ^TSmallRecord;
|
||||||
TSmallRecord = packed record
|
TSmallRecord = packed record
|
||||||
a,b,c: byte;
|
a,b,c: byte;
|
||||||
//d: byte;
|
//d : Integer;
|
||||||
|
d: byte;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
const
|
const
|
||||||
@ -50,6 +51,7 @@ const
|
|||||||
newMethod5 = 'getSmallRecord';
|
newMethod5 = 'getSmallRecord';
|
||||||
newMethod5Enc = '{TSmallRecord=ccc}@:';
|
newMethod5Enc = '{TSmallRecord=ccc}@:';
|
||||||
|
|
||||||
|
varName = 'myvar';
|
||||||
|
|
||||||
function imp_init(self: id; _cmd: SEL): id; cdecl;
|
function imp_init(self: id; _cmd: SEL): id; cdecl;
|
||||||
var
|
var
|
||||||
@ -79,12 +81,12 @@ begin
|
|||||||
Result := 3.125;
|
Result := 3.125;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure imp_getSmallRec(Result: PSmallRecord; seld: id; _cmd: SEL); cdecl;
|
function imp_getSmallRec(seld: id; _cmd: SEL): TSmallRecord; cdecl;
|
||||||
begin
|
begin
|
||||||
Result^.a := 121;
|
Result.a := 121;
|
||||||
Result^.b := 68;
|
Result.b := 68;
|
||||||
Result^.c := 22;
|
Result.c := 22;
|
||||||
//Result.d := 5;
|
Result.d := 5;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
@ -101,13 +103,23 @@ begin
|
|||||||
class_addMethod(cl, selector(newMethod4), @imp_newMethod4, newMethod4Enc);
|
class_addMethod(cl, selector(newMethod4), @imp_newMethod4, newMethod4Enc);
|
||||||
class_addMethod(cl, selector(newMethod5), @imp_getSmallRec, newMethod5Enc);
|
class_addMethod(cl, selector(newMethod5), @imp_getSmallRec, newMethod5Enc);
|
||||||
if not b then writeln('failed to add/override some method(s)');
|
if not b then writeln('failed to add/override some method(s)');
|
||||||
|
|
||||||
|
class_addIvar(cl, varName, sizeof(TObject), 1, _C_PASOBJ);
|
||||||
|
|
||||||
objc_registerClassPair(cl);
|
objc_registerClassPair(cl);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
var
|
var
|
||||||
obj : id;
|
obj : id;
|
||||||
stret : TSmallRecord;
|
objvar : Ivar;
|
||||||
buf : array [0..255] of byte;
|
|
||||||
|
stret : TSmallRecord;
|
||||||
|
varobj : TObject;
|
||||||
|
p : Pointer;
|
||||||
|
|
||||||
|
type
|
||||||
|
TgetSmallRecord = function (obj: id; cmd: Sel; arg: array of const): TSmallRecord; cdecl;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
// if InitializeObjcRtl20(DefaultObjCLibName) then // should be used of OSX 10.5 and iPhoneOS
|
// if InitializeObjcRtl20(DefaultObjCLibName) then // should be used of OSX 10.5 and iPhoneOS
|
||||||
|
|
||||||
@ -119,27 +131,32 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
RegisterSubclass(newClassName);
|
RegisterSubclass(newClassName);
|
||||||
|
writeln('registered');
|
||||||
|
|
||||||
obj := AllocAndInit(newClassName);
|
obj := AllocAndInit(newClassName);
|
||||||
{obj := alloc(newClassName);
|
{obj := alloc(newClassName);
|
||||||
objc_msgSend(obj, selector(overrideMethod), []);}
|
objc_msgSend(obj, selector(overrideMethod), []);}
|
||||||
|
|
||||||
|
writeln('sizeof(TSmallRecord) = ', sizeof(TSmallRecord));
|
||||||
|
stret := TgetSmallRecord(objc_msgSend_stretreg)(obj, selector(newMethod5), []);
|
||||||
|
//writeln('p = ', Integer(p));
|
||||||
|
|
||||||
|
//stret :=
|
||||||
|
writeln('stret.a = ', stret.a);
|
||||||
|
writeln('stret.b = ', stret.b);
|
||||||
|
writeln('stret.c = ', stret.c);
|
||||||
|
writeln('stret.d = ', stret.d);
|
||||||
|
|
||||||
|
//PInteger(@stret)^ := Integer(objc_msgSend(obj, selector(newMethod5), []));
|
||||||
|
|
||||||
objc_msgSend(obj, selector(newMethod1), []);
|
objc_msgSend(obj, selector(newMethod1), []);
|
||||||
objc_msgSend(obj, selector(newMethod2), [5, 4]);
|
objc_msgSend(obj, selector(newMethod2), [5, 4]);
|
||||||
|
|
||||||
writeln('get double = ', objc_msgSend_fpret(obj, selector(newMethod3), []));
|
writeln('get double = ', objc_msgSend_fpret(obj, selector(newMethod3), []));
|
||||||
writeln('get float = ', objc_msgSend_fpret(obj, selector(newMethod4), []));
|
writeln('get float = ', objc_msgSend_fpret(obj, selector(newMethod4), []));
|
||||||
|
|
||||||
writeln('sizeof(TSmallRecord) = ', sizeof(TSmallRecord));
|
|
||||||
objc_msgSend_stret(@stret, obj, selector(newMethod5), []);
|
|
||||||
writeln('stret.a = ', stret.a);
|
|
||||||
writeln('stret.b = ', stret.b);
|
|
||||||
writeln('stret.c = ', stret.c);
|
|
||||||
|
|
||||||
release( obj );
|
release( obj );
|
||||||
|
|
||||||
writeln('test successfully complete');
|
writeln('test successfully complete');
|
||||||
|
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user