[Openmcl-devel] Defining new objective C types

Michael Minerva minerva at agentsheets.com
Wed Mar 9 14:58:33 PST 2011

Thank you very much for your very detailed and insightful response.  All of the details about foreign types was something I had always been curious about, so even though it was not the cause of my problem this time, I am very thankful to have that information.  Also, your "shorter version" did in fact describe my problem (once I put the timer in the main thread everything worked fine).  Thanks a lot!

On Mar 9, 2011, at 3:14 PM, Gary Byers wrote:

> The short version is that the foreign type :id describes anything that's
> "a foreign pointer to an ObjC object".  The ObjC declaration
> - (void)timerFireMethod:(NSTimer*)theTimer
> 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
> any clearer.
> 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
>  fine.)
> 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
>> (#/scheduledTimerWithTimeInterval:target:selector:userInfo:repeats:
>> 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
>> method?#/scheduledTimerWithTimeInterval:target:selector:userInfo:repeats:
>> 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,
>> --Mike

More information about the Openmcl-devel mailing list