Hi all,
Objective-CL 0.2.0 has been released. This release is a major milestone on the way to 1.0.0.
* Quick summary
We can now define Objective-C classes and methods without writing a single line of Objective-C code. The API may not be stable and there might be crashes, but living dangerously is half the fun, right? ;)
* What's new?
** Method call syntax
#.(enable-method-syntax)
We now support Clozure CL's new method call syntax via reader macros. That means you can write:
(let ((lock (#/new (find-objc-class 'ns-lock)))) (#/lock lock) (print (#/stringWithCString:encoding: (find-objc-class 'ns-string) "Hi there!" 0)) (#/unlock lock))
In fact, as the reader macro does no more than offer an alternate syntax for symbols, you can do things like using it with APPLY as well:
(apply #'#/stringWithUTF8String: (find-objc-class 'ns-string) (list "Hi again."))
** Class definition
You can now define classes. For example, the following will define a subclass of NSObject called MLKMyClass, including a native slot called FOOS and a foreign slot (that is, an Objective-C ivar) called FOO-COUNT (fooCount on the Objective-C side):
(define-objective-c-class ns::mlk-my-class (ns::ns-object) ((foos :initargs :foos) (foo-count :foreign-type :int)))
Simple CFFI type specifiers are recognised by :FOREIGN-TYPE, but please note that complex types such as struct and union types are not yet supported.
** Method definition
You can now define Objective-C methods from Lisp for your own classes. The following will define the Objective-C method -(int)foo:(int)bar:(id)stuff:(id)do:(NSNumber *) on MLKMyClass instances:
(define-objective-c-generic-function #/foo:bar:stuff:do: (self y z a b))
(define-objective-c-method #/foo:bar:stuff:do: :int ((self ns::mlk-my-class) (y :int) z a (b ns::ns-number)) (format t "Hello! Z and A are ~A and~&~A, respectively. Have a nice day." z a) (+ y 20))
Usage example:
OBJECTIVE-CL> (invoke (invoke (find-objc-class 'mlk-my-class) 'new) :foo 3 :bar "abc" :stuff 3 :do 33) Hello! Z and A are #<NS:GSC-BUFFER-STRING `abc' {8230318}> and #<NS:GS-CACHED-INT `3' {812C5D0}>, respectively. Have a nice day. 23
Note that, at present, you absolutely have to call DEFINE-OBJECTIVE-C-GENERIC-FUNCTION before defining methods, because otherwise you're going to get the wrong type of generic function.
All modifiers of the standard method combination should be supported in principle, but it's unlikey they'll work as expected. This is planned for a future release.
&REST and &KEY arguments are not supported.
#.(disable-method-syntax)
** Struct wrappers
When an Objective-C method returns a struct, it is now wrapped in a FOREIGN-STRUCT; likewise for unions. If you want to prevent its automatic deallocation, you need to set its FOREIGN-VALUE-LISP-MANAGED-P property to false. This change has been made because it would otherwise not be safe to discard return values of Objective-C methods, a safety which both Objective-C and Lisp programmers have come to expect.
** COLLECT-CLASSES
The new function COLLECT-CLASSES may be used to make all classes known to the Objective-C runtime available as CLOS classes under the NS namespace. In an ideal world, we'd do this automatically at system load-time, but registering such a large number of classes along with their metaclasses takes a long time on some CL implementations (CMUCL, SBCL), so it's the user's decision whether to use FIND-OBJC-CLASS for each class or COLLECT-CLASSES once for now.
If you try the release out, please tell me what works and what doesn't. If you can't even get it to compile, that is helpful information as well.
Of course, above all, have lots of fun!
~ Matthias