toc: tags: eggs
== objc
=== Requirements
make matchable miscmacros fmt concurrent-native-callbacks
This extension makes use of dyncall, a library for constructing C function-calls at runtime. The library needs to be installed for this egg to function properly.
=== Introduction
This egg provides a leightweight interface to Objective-C. It has been tested on Linux with GNUstep and Mac OS X.
This egg is part of the chicken-mobile project. The sources are available here: https://github.com/chicken-mobile/concurrent-native-callbacks
=== Programming interface
==== Declarations and definitions
<syntax>(objc-import IMPORT ...)</syntax>
Expands into an preprocessor directive, the string designates an Objective-C headerfile and can alternatively be of the form .
This form is only available in compiled code.
<syntax>(define-objc-class NAME)</syntax>
Forward-declares an Objective-C class by expanding into a declaration.
This form can only be used in compiled code.
<syntax>(define-objc-interface NAME [:] DECLARATION ...)</syntax>
Defines an interface (as in ). and the optional should be symbols and valid Objective-C classnames.
A consists of field or method specifications:
Declaring a "field" (an instance variable):
Declaring a class or instance method (unary):
Declaring a class or instance method with arguments:
may be omitted and defaults to .
and follow normal foreign-type syntax. In addition to the usual foreign type specifiers, the types , and are also available and correspond to .
Note that this declaration is only valid inside the current compilation unit.
This form may only be used in compiled code.
<syntax>(define-objc-implementation NAME DEFINITION ...)</syntax>
Defines an implementation section for methods of the class (as in ).
should be of the form
where follows the syntax given above for . Additionally, asynchronously callable methods can be defined (see below).
Inside the expressions the implicit variable refers to the current receiver.
This form can only be used in compiled code.
==== Method invocation
<syntax>(send RECEIVER SELECTOR ARGUMENT ...)</syntax>
Sends the message given in the symbol or keyword to the object with the given arguments and returns its result.
<syntax>(send/block RECEIVER SELECTOR ARGUMENT ...)</syntax>
Returns a C block pointer, that, when invoked will send the message with the arguments given. Note that the receiver and the arguments are evaluated when the block is created. The returned block is heap-allocated. Use to release the memory.
This syntax is only available on Mac OS X / iOS.
<syntax>(send/main-thread RECEIVER SELECTOR ARGUMENT ...)</syntax>
Creates a C block wrapping the method-invocation and adds it to the dispatch queue of the main thread.
This syntax is only available on Mac OS X / iOS.
<syntax>(@selector NAME)</syntax>
Returns the selector with the given name, which should be a symbol or keyword. The is not evaluated.
<syntax>(@ RECEIVER SELECTOR ARGUMENT ...)</syntax> <syntax>(@/block RECEIVER SELECTOR ARGUMENT ...)</syntax> <syntax>(@/main-thread RECEIVER SELECTOR ARGUMENT ...)</syntax>
A slightly more convenient syntax for sending messages:
- is equivalent to .
- is equivalent to . The receiver may be the special variable which sends to a message to but starts the message-lookup in the superclass of the receiver (this is only valid inside a method-implementation).
==== Objects
<procedure>(object? X)</procedure>
Returns true if is an object- or class-pointer or otherwise.
<procedure>(object-ref OBJECT SYMBOL)</procedure>
Returns the instance-variable named of the given instance.
<procedure>(object-set! OBJECT SYMBOL X)</procedure>
Assigns to the instance-variable of the given instance. Alternatively you can also use the form .
<variable>nil</variable>
The same as which is CHICKEN's representation of a NULL pointer.
==== Classes
<class>Object</class>
Holds a pointer to class .
<procedure>(class? X)</procedure>
Returns true if is a class-pointer or otherwise.
<procedure>(metaclass? X)</procedure>
Returns true if is a pointer to a meta-class or otherwise.
<procedure>(class-of OBJECT)</procedure>
Returns a pointer to the class of the given object. If is a class, the result will be a metaclass instance.
<procedure>(class-name CLASS)</procedure>
Returns the name of the given class, which is a string.
<procedure>(find-class NAME)</procedure>
Finds the class with the given name (which should be string) or if no such class exists.
<procedure>(superclass-of CLASS)</procedure>
Returns the superclass of the given class or if is a root class.
==== Selectors
<procedure>(selector? X)</procedure>
Returns true if is a selector-pointer or otherwise.
<procedure>(string->selector STRING)</procedure>
Returns a pointer to the selector object for the selector with the name .
<procedure>(selector->string SELECTOR)</procedure>
Returns the name of the given selector-pointer.
==== Asynchronously callable methods
Methods defined with or inside a declaration may (and must) be called from a native thread other than the thread in which the CHICKEN runtime system executes:
<enscript highlight="scheme"> (define-objc-implementation Foo ((-/async ping: (int)x) (print "ping: " x) self)) </scheme></enscript>
The implementation of asychronously callable methods uses the concurrent-native-callbacks internally.
Note: calling such a method from the same thread will block indefinitely. ==== Blocks
<procedure>(block-copy BLOCK)</procedure>
Allocates and copies the block referenced to by the block-pointer , which is either the result of claling or . The copied block is returned.
On platforms other than Mac OS X / iOS, this procedure does nothing and returns .
<procedure>(block-release! BLOCK)</procedure>
Releases the memory occupied by the previously copied block .
On platforms other than Mac OS X / iOS, this procedure does nothing.
==== Method-call read-syntax
<syntax>[RECEIVER]</syntax>
A convenience read-syntax to make method-invocations look more natural. It is entirely equivalent to . To use this syntax, pass
-X objc-read-syntax
to the compiler when compiling Scheme code using this syntax, or use
(use objc-read-syntax)
in interpreted code. Note that is often used as an alternative to , which is the default behaviour in the CHICKEN reader.
=== Restrictions
A number of restrictions and limitations exist:
- Class-declaration and -definition is only possible in compiled code.
- Instances, classes and selectors are generally passed around as "tagged pointers" which is relatively lightweight but shows little information about the object when printed.
- All method calls are implicitly "safe", they allow callbacks (as in . This is slower than using unsafe calls. Currently there is no unsafe method-invocation variant.
- Instance-variables can be assigned strings or vectors or any structured data in general, if the data belongs to Scheme.
- Method-call performance is not particularly good.
On newer Linux systems, dynamic loading of shared objects that are marked as having an executable stack area will result in a runtime-error. This applies mostly to code that has been built from assembler sources and is in fact the case in the dyncall library. This issue will be fixed in the next release of but in the time being you can apply the following patch tot he sources:
=== Version History
- 0.1 : initial release
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the author nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.