[Openmcl-devel] Defining new objective C types
gb at clozure.com
Wed Mar 9 16:14:37 CST 2011
The short version is that the foreign type :id describes anything that's
"a foreign pointer to an ObjC object". The ObjC declaration
says that the parameter is a pointer to (an instance of) a specific
type of ObjC object (an NSTimer); it would have been correct to have
said that the parameter was of type "id", but the more specific type
helps the ObjC compiler do some compile-time typechecking and tells
the human reader that the parameter will be an NSTimer.
Note that the syntax - NSTimer*, "pointer to something of type
NSTimer" - is essentially the same as would be used to describe a
pointer to an NSRect or pointer to int or other foreign type. At some
level in ObjC, the NSTimer is defined as a structure type (in the same
way that NSRect is a structure type), but there's a tradeoff there:
you generally want to think of an NSTimer as being something whose
representation is a lot more opaque than an NSRect's is. (An NSTimer
is a few notches above an NSRect on the food chain.)
The interface files define "NSRect" to be the name of a foreign type
(with an associated struct definition) and also the name of an ObjC
class. The former can be referred to as :<NSR>ect (which is easier
to write and read as #>NSRect) and the latter as NS:NS-RECT. The
pointer to the timer method's parameter is both "a pointer to something
described by the foreign type #>NSTimer" and "an instance of the NS:NS-TIMER
class", and at some level those are basically the same thing; the former
is a "foreign type" in CCL and the latter is a lisp type.
OBJC:DEFMETHOD wants to know the foreign types of the method's arguments.
We generally don't want to have to say that a parameter that's an instance
of an ObjC class is a pointer to some random foreign type (it's further
up the food chain than that), so it's easier to just say that the foreign
type is just :id ("some kind of ObjC object"). It's be nice if OBJC:DEFMETHOD
accepted ObjC class names and treated them as if they named a specific subclass
of :id; that'd help the human reader (and writer) of the method definition and
might help the compiler in some cases. We haven't done that, and essentially
all of the :id-typed parameters to all of the methods that we/you/others have
written are just declared/defaulted to be of type :id. If you really wanted
to do so, you could say that the timer method's arg was of type (:* #>NSTimer),
but that wouldn't really affect anything and probably doesn't make anything
The even shorter version (which might have been better) is "this has nothing
to do with why your timer method isn't printing anything." Some things that
might explain this:
- #/scheduledTimerWithTimeInterval:target:selector:userInfo:repeats: is defined
to add the timer to the "current run loop", which is another way of saying
"to the current thread's run loop." A run loop (the short version) is
a thread-specific object that describes a set of event sources; when a
thread "runs its run loop", it does whatever it needs to do to sample
those sources. The main event thread runs its run loop almost all the
time (it's almost always waiting for those event sources or responding
to the events - with a small #\e - that occur). Other threads generally
don't run their run loops unless explicitly told to do so.
What run loop is current when the method that establishes the timer is
called ? E.g., what thread does that code run in ?
- I don't know either way, but it's certainly possible and wouldn't be
surprising if NSTimers in general (or this particular way of establishing
one) just don't/doesn't work in Cocotron. (I'm fairly sure that I've
seen NSTimer-related code in the sources and if it didn't work it'd
be more a case of "mostly/entirely implemented but broken for some
reason" rather than "just stubbed out and not really implemented",
and for all I know - which isn't much - the code's all there and works
On Wed, 9 Mar 2011, Michael Minerva wrote:
> I am curious if there is a way to define a new objc type that will be
> recognized by objc methods as a parameter, I thought I could just find
> where?:<NSI>nteger was defined but I had no luck when I looked for that
> definition. ?Most of the time you can just list your parameter without a
> type but it seems that in the case of an NSTimer you may need to define the
> type explicitly. ? Here is my little example that seems to need this
> explicit type definition for the timer parameter:
> (defclass COCOTRON-VIEW (ns:ns-opengl-view)
> ??(:metaclass ns:+ns-object))
> (defun COCOTRON-TEST ()
> ??(ns:with-ns-rect (frame 0 0 200 200)
> ?? ?(let* ((window (make-instance ns:ns-window :height 300))
> ?? ? ? ? ?(opengl-view (#/retain (#/initWithFrame:pixelFormat: (#/alloc
> cocotron-view) frame (#/defaultPixelFormat ns:ns-opengl-view))))
> ?? ? ? ? ?(timer (#/retain
> ns:ns-timer .01d0 opengl-view (objc::@selector #/timer:) nil #$YES))))
> ;;***********This is the line of importance***************
> ?? ? ?(#/orderFront: window nil))))
> ?? ? ?
> (objc:defmethod (#/timer: :void) ((self cocotron-view) timer)
> ??(print "TIMER"))
> It seems to me that this code should work but timer is never printed, I
> believe the problem is because I am not explicitly defining the type of the
> parameter. ?The documentation of the
> states that the selector must have the following signature:
> - (void)timerFireMethod:(NSTimer*)theTimer
> So I assume my problem is that I am defining the type of the timer loosely.
> ?Anyone know how I could explicitly define the parameter in this example?
> ?Something like this: ?
> (objc:defmethod (#/timer: :void) ((self cocotron-view) (timer ns:ns-timer))
> ??(print "TIMER"))
> gives this error:
> > Error: Unknown foreign type: NS:NS-TIMER
> > While executing: CCL::%PARSE-FOREIGN-TYPE, in process Listener(11).
> > Type cmd-. to abort, cmd-\ for a list of available restarts.
> > Type :? for other options.
> 6 >?
> Thanks a lot,
More information about the Openmcl-devel