5.10 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.10.1 FFI Types and Constants
5.10.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 :.
Examples: | ||||||
|
syntax
(import-class class-id ...)
Example: | |||
|
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 X, 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 ...)
Example: | |||
|
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.
Example: | ||||||||||||
|
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)
Example: | |||
|
procedure
(objc-is-a? obj cls) → boolean?
obj : _id cls : _Class
5.10.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_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
5.10.4 Legacy Library
syntax