objcrtltest.pas 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. {
  2. Objective-C rtl Test application by dmitry boyarintsev
  3. Should compile and run with no problems
  4. program output should look like:
  5. Objective-C runtime initialized successfuly
  6. -init method
  7. called newMethod1
  8. called newMethod2, a = 5; b = 4
  9. get double = 1.33300000000000E+000
  10. get float = 3.12500000000000E+000
  11. test successfully complete
  12. }
  13. program objcrtltest;
  14. {$mode objfpc}{$H+}
  15. uses
  16. objcrtl20, objcrtl10, objcrtl, objcrtlutils;
  17. {.$linkframework AppKit}
  18. {$linkframework Foundation}
  19. type
  20. TSubStructure = packed record
  21. a,b,c,d: byte;
  22. end;
  23. PSmallRecord = ^TSmallRecord;
  24. TSmallRecord = packed record
  25. a,b,c: byte;
  26. //d : Integer;
  27. d: byte;
  28. sub: TSubStructure;
  29. end;
  30. const
  31. newClassName = 'NSMyObject';
  32. overrideMethod = 'init';
  33. overrideMethodEnc = '@@:';
  34. newMethod1 = 'newMethod1';
  35. newMethod1Enc = 'v@:';
  36. newMethod2 = 'newMethod2::';
  37. newMethod2Enc = 'v@:ii';
  38. newMethod3 = 'getDouble';
  39. newMethod3Enc = 'd@:';
  40. newMethod4 = 'getFloat';
  41. newMethod4Enc = 'f@:';
  42. newMethod5 = 'getSmallRecord';
  43. newMethod5Enc = '{TSmallRecord=cccc{TSubStructure=cccc}}@:';
  44. varName = 'myvar';
  45. function imp_init(self: id; _cmd: SEL): id; cdecl;
  46. var
  47. sp : objc_super;
  48. begin
  49. writeln('-init method');
  50. sp := super(self);
  51. Result := objc_msgSendSuper(@sp, selector(overrideMethod), []);
  52. end;
  53. procedure imp_newMethod1(self: id; _cmd: SEL); cdecl;
  54. begin
  55. writeln('called newMethod1');
  56. end;
  57. procedure imp_newMethod2(self: id; _cmd: SEL; a, b: Integer); cdecl;
  58. begin
  59. writeln('called newMethod2, a = ', a, '; b = ', b);
  60. end;
  61. function imp_newMethod3(self: id; _cmd: SEL): Double; cdecl;
  62. begin
  63. Result := 1.333;
  64. end;
  65. function imp_newMethod4(self: id; _cmd: SEL): Single; cdecl;
  66. begin
  67. Result := 3.125;
  68. end;
  69. function imp_getSmallRec(seld: id; _cmd: SEL): TSmallRecord; cdecl;
  70. begin
  71. Result.a := 121;
  72. Result.b := 68;
  73. Result.c := 22;
  74. Result.d := 5;
  75. end;
  76. procedure RegisterSubclass(NewClassName: PAnsiChar);
  77. var
  78. cl : _Class;
  79. b : Boolean;
  80. begin
  81. cl := objc_allocateClassPair(objc_getClass('NSObject'), NewClassName, 0);
  82. b := class_addMethod(cl, selector(OverrideMethod), @imp_init, overrideMethodEnc) and
  83. class_addMethod(cl, selector(newMethod1), @imp_newMethod1, newMethod1Enc) and
  84. class_addMethod(cl, selector(newMethod2), @imp_newMethod2, newMethod2Enc) and
  85. class_addMethod(cl, selector(newMethod3), @imp_newMethod3, newMethod3Enc) and
  86. class_addMethod(cl, selector(newMethod4), @imp_newMethod4, newMethod4Enc) and
  87. class_addMethod(cl, selector(newMethod5), @imp_getSmallRec, newMethod5Enc);
  88. if not b then
  89. writeln('failed to add/override some method(s)');
  90. if not class_addIvar(cl, varName, sizeof(TObject), 1, _C_PASOBJ) then
  91. writeln('failed to add variable ', varName);
  92. objc_registerClassPair(cl);
  93. end;
  94. var
  95. obj : id;
  96. objvar : Ivar;
  97. stret : TSmallRecord;
  98. varobj : TObject;
  99. {$WARNINGS OFF} // cdecl'ared functions have no high parameter
  100. type
  101. TgetSmallRecord = function (obj: id; cmd: Sel; arg: array of const): TSmallRecord; cdecl;
  102. {$WARNINGS ON}
  103. begin
  104. // if InitializeObjcRtl20(DefaultObjCLibName) then // should be used of OSX 10.5 and iPhoneOS
  105. if InitializeObjcRtl10(DefaultObjCLibName) then // should be used of OSX 10.4 and lower
  106. writeln('Objective-C runtime initialized successfuly')
  107. else begin
  108. writeln('failed to initialize Objective-C runtime');
  109. Halt;
  110. end;
  111. RegisterSubclass(newClassName);
  112. writeln('registered');
  113. obj := AllocAndInit(newClassName);
  114. {obj := alloc(newClassName);
  115. objc_msgSend(obj, selector(overrideMethod), []);}
  116. writeln('sizeof(TSmallRecord) = ', sizeof(TSmallRecord));
  117. // this must be resolved at code-time (or compiler-time), not run-time
  118. {$WARNINGS OFF} // unreachable code
  119. if sizeof(TSmallRecord) in [1,2,4,8] then
  120. stret := TgetSmallRecord(objc_msgSend_stretreg)(obj, selector(newMethod5), [])
  121. else
  122. stret := TgetSmallRecord(objc_msgSend_stret)(obj, selector(newMethod5), []);
  123. {$WARNINGS ON}
  124. //writeln('p = ', Integer(p));
  125. //stret :=
  126. writeln('stret.a = ', stret.a);
  127. writeln('stret.b = ', stret.b);
  128. writeln('stret.c = ', stret.c);
  129. writeln('stret.d = ', stret.d);
  130. objc_msgSend(obj, selector(newMethod1), []);
  131. objc_msgSend(obj, selector(newMethod2), [5, 4]);
  132. writeln('get double = ', objc_msgSend_fpret(obj, selector(newMethod3), []));
  133. writeln('get float = ', objc_msgSend_fpret(obj, selector(newMethod4), []));
  134. objvar := class_getInstanceVariable( object_getClass(obj), varName);
  135. varobj := TObject.Create;
  136. writeln('var Value = ', Integer(object_getIvar(obj, objvar)));
  137. writeln('setting new Value = ', Integer(varobj));
  138. object_setIvar(obj, objvar, varobj);
  139. writeln('var Value = ', Integer(object_getIvar(obj, objvar)));
  140. writeln('var offset = ', Integer(ivar_getOffset(objvar)));
  141. writeln('var name = ', ivar_getName(objvar));
  142. writeln('var type = ', ivar_getTypeEncoding(objvar));
  143. release(obj);
  144. varobj.Free;
  145. writeln('test successfully complete');
  146. end.