5.16 Objective-C FFI
(require ffi/unsafe/objc) | package: base |
The library supports Objective-C interaction in two layers. The upper layer provides syntactic forms for sending messages and deriving subclasses. The lower layer is a thin wrapper on the Objective-C runtime library functions. Even the upper layer is unsafe and relatively low-level compared to normal Racket libraries, because argument and result types must be declared in terms of FFI C types (see Type Constructors).
5.16.1 FFI Types and Constants
5.16.2 Syntactic Forms and Procedures
syntax
(tell result-type obj-expr method-id)
(tell result-type obj-expr arg ...)
result-type =
| #:type ctype-expr arg = method-id arg-expr | method-id #:type ctype-expr arg-expr
If a single method-id is provided with no arguments, then method-id must not end with :; otherwise, each method-id must end with :.
> (tell NSString alloc) #<cpointer:id>
> (tell (tell NSString alloc) initWithUTF8String: #:type _string "Hello") #<cpointer:id>
syntax
(import-class class-id ...)
> (import-class NSString)
A class accessed by import-class is normally declared as a side effect of loading a foreign library. For example, if you want to import the class NSString on Mac OS, the "Foundation" framework must be loaded, first. Beware that if you use import-class in DrRacket or a module that requires racket/gui/base, then "Foundation" will have been loaded into the Racket process already. To avoid relying on other libraries to load "Foundation", explicitly load it with ffi-lib:
> (ffi-lib "/System/Library/Frameworks/Foundation.framework/Foundation") > (import-class NSString)
syntax
(import-protocol protocol-id ...)
> (import-protocol NSCoding)
syntax
(define-objc-class class-id superclass-expr maybe-mixins maybe-protocols [field-id ...] method ...)
maybe-mixins =
| #:mixins (mixin-expr ...) maybe-protocols =
| #:protocols (protocol-expr ...) method = (mode maybe-async result-ctype-expr (method-id) body ...+) | (mode maybe-async result-ctype-expr (arg ...+) body ...+) mode = + | - | +a | -a maybe-async =
| #:async-apply async-apply-expr arg = method-id [ctype-expr arg-id]
Each field-id is an instance field that holds a Racket value and that is initialized to #f when the object is allocated. The field-ids can be referenced and set! directly when the method bodys. Outside the object, they can be referenced and set with get-ivar and set-ivar!.
Each method adds or overrides a method to the class (when mode is - or -a) to be called on instances, or it adds a method to the meta-class (when mode is + or +a) to be called on the class itself. All result and argument types must be declared using FFI C types (see Type Constructors). When mode is +a or -a, the method is called in atomic mode (see _cprocedure). An optional #:async-apply specification determines how the method works when called from a foreign thread in the same way as for _cprocedure.
If a method is declared with a single method-id and no arguments, then method-id must not end with :. Otherwise, each method-id must end with :.
If the special method dealloc is declared for mode -, it must not call the superclass method, because a (super-tell dealloc) is added to the end of the method automatically. In addition, before (super-tell dealloc), space for each field-id within the instance is deallocated.
> (define-objc-class MyView NSView [bm] ; <- one field (- _racket (swapBitwmap: [_racket new-bm]) (begin0 bm (set! bm new-bm))) (- _void (drawRect: [_NSRect exposed-rect]) (super-tell drawRect: exposed-rect) (draw-bitmap-region bm exposed-rect)) (- _void (dealloc) (when bm (done-with-bm bm))))
Changed in version 6.90.0.26 of package base: Changed #:protocols handling to ignore #f expression results.
syntax
(define-objc-mixin (class-id superclass-id) maybe-mixins maybe-protocols [field-id ...] method ...)
syntax
syntax
(super-tell result-type method-id)
(super-tell result-type arg ...)
syntax
(get-ivar obj-expr field-id)
syntax
(set-ivar! obj-expr field-id value-expr)
syntax
(selector method-id)
procedure
(objc-is-a? obj cls) → boolean?
obj : _id cls : _Class
Changed in version 6.1.0.5 of package base: Recognize subclasses, instead of requiring an exact class match.
procedure
(objc-subclass? subcls cls) → boolean?
subcls : _Class cls : _Class
Added in version 6.1.0.5 of package base.
procedure
(objc-get-class obj) → _Class
obj : _id
Added in version 6.3 of package base.
procedure
(objc-set-class! obj cls) → void?
obj : _id cls : _Class
Added in version 6.3 of package base.
procedure
(objc-get-superclass cls) → _Class
cls : _Class
Added in version 6.3 of package base.
procedure
(objc-dispose-class cls) → void?
cls : _Class
Added in version 6.3 of package base.
procedure
(objc-block function-type? proc #:keep keep) → cpointer?
function-type? : ctype proc : procedure? keep : (box/c list?)
Extra records that are allocated to implement the block are added to the list in keep, which might also be included in function-type through a #:keep option to _fun. The pointers registered in keep must be retained as long as the block remains in use.
Added in version 6.3 of package base.
procedure
(objc-block-function-pointer block) → fpointer?
block : cpointer?
Added in version 8.13.0.1 of package base.
syntax
(with-blocking-tell form ...+)
Added in version 7.0.0.19 of package base.
5.16.3 Raw Runtime Functions
procedure
(objc_lookUpClass s) → (or/c _Class #f)
s : string?
procedure
(objc_getProtocol s) → (or/c _Protocol #f)
s : string?
procedure
(sel_registerName s) → _SEL
s : string?
procedure
(objc_allocateClassPair cls s extra) → _Class
cls : _Class s : string? extra : integer?
procedure
(objc_registerClassPair cls) → void?
cls : _Class
procedure
(object_getClass obj) → _Class
obj : _id
procedure
(class_getSuperclass cls) → _Class
cls : _Class
Added in version 6.1.0.5 of package base.
procedure
(class_addMethod cls sel imp type type-encoding) → boolean? cls : _Class sel : _SEL imp : procedure? type : ctype? type-encoding : string?
procedure
(class_addIvar cls name size log-alignment type-encoding) → boolean? cls : _Class name : string? size : exact-nonnegative-integer? log-alignment : exact-nonnegative-integer? type-encoding : string?
procedure
(object_getInstanceVariable obj name) →
_Ivar any/c obj : _id name : string?
procedure
(object_setInstanceVariable obj name val) → _Ivar
obj : _id name : string? val : any/c
procedure
((objc_msgSend/typed types) obj sel arg) → any/c
types : (vector/c result-ctype arg-ctype ...) obj : _id sel : _SEL arg : any/c
procedure
((objc_msgSendSuper/typed types) super sel arg) → any/c types : (vector/c result-ctype arg-ctype ...) super : _objc_super sel : _SEL arg : any/c
procedure
(make-objc_super id super) → _objc_super
id : _id super : _Class
value
procedure
((objc_msgSend/typed/blocking types) obj sel arg) → any/c types : (vector/c result-ctype arg-ctype ...) obj : _id sel : _SEL arg : any/c
procedure
((objc_msgSendSuper/typed/blocking types) super sel arg) → any/c types : (vector/c result-ctype arg-ctype ...) super : _objc_super sel : _SEL arg : any/c
Added in version 7.0.0.19 of package base.
5.16.4 Legacy Library
syntax