[MacRuby-devel] Porting Cocoa OpenGL sample code

Matt Aimonetti mattaimonetti at gmail.com
Wed Feb 25 13:16:59 PST 2009


Thanks Brian for the detailed explanation. I wonder if your Pointer
extension shouldn't be merged into HotCocoa or MacRuby itself.

What do you guys think?

- Matt

On Wed, Feb 25, 2009 at 12:43 PM, Brian Chapados <chapbr at gmail.com> wrote:
>> Can you explain: "^{_CGLRendererInfoObject=}"? is that some secret
>> incantation only known by the MacRuby/Obj overlords?
>
> Yes, it is actually a 7th level spell: 'Encode Structure'.  To learn
> it, you must study the ancient tome:
> http://developer.apple.com/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/chapter_7_section_1.html#//apple_ref/doc/uid/TP40008048-CH100-SW1
>
>  If it makes you feel better, I usually need to look it up (or just
> run the Obj-C code sample), unless it is something simple (like '@').
> I don't keep this spell in memory, as it is only required in special
> situations.
>
> Seriously though, that is actually how you encode a pointer to a
> struct.  If you use the @encode(type) directive, the compiler will
> return the runtime encoding for 'type'.  It's a bit cryptic, but not
> too bad once you know the syntax:
>
> '^type' encodes a pointer to type.
> '{name=<field1 type><field2 type><field3 type>...<fieldN type>}'
> encodes a struct with N fields.
>
> To break it down using 2 examples:
>
> (from the docs)
> typedef struct example {
>    id   anObject; // encoding = @
>    char *aString; // encoding = c
>    int  anInt; // enoding = i
> } Example;
>
> @encode(Example) = "^{example=@ci}"
>
> CGLRendererInfoObj is a pointer to an opaque struct (we don't know
> anything about the fields) named _CGLRendererInfoObject. All we know
> is:
> typedef struct _CGLRendererInfoObject *CGLRendererInfoObj;
>
> so it's just "^{_CGLRendererInfoObject=}"
>
> In practice (unless you're working with CoreFoundation C APIs) you
> usually just need a pointer to an object.  The most common usage I run
> across is to retrieve NSError objects.  The CoreFoundation C API uses
> pass-by-reference extensively.  To use these functions with MacRuby,
> you need to create lots of pointer objects. In general, this is an
> area where interfacing ruby with C is just fugly.  I'd personally
> avoid doing this in MacRuby.  If you find yourself needing to use lots
> Pointer objects, it's probably better and less error-prone to write
> that code in C and expose it to MacRuby through an Objective-C
> interface.
>
> That said, for common things, I've used something like this extension
> to the Pointer class:
>
> ----
> class Pointer
>  def self.ptr
>    new_with_type("@")
>  end
>
>  def self.to(type = :object)
>    case type
>      when :object
>        new_with_type('@')
>      when :int
>        new_with_type('i')
>      when :char
>      when :bool
>      when :BOOL
>        new_with_type('c')
>      when :unsigned
>        new_with_type('I')
>    end
>  end
>
>  def value
>    self[0]
>  end
> end
>
> ----
>
> Need a pointer to an ObjC object?
> p = Pointer.ptr
>
> To a BOOL?
> p = Pointer.to(:BOOL)
>
> Need the value?
> p.value
>
> Those are the most common types I've needed.
>
> On Wed, Feb 25, 2009 at 11:11 AM, Matt Aimonetti
> <mattaimonetti at gmail.com> wrote:
>> Brian, what's up with this syntax: info =
>> Pointer.new_with_type("^{_CGLRendererInfoObject=}")
>> Can you explain: "^{_CGLRendererInfoObject=}"? is that some secret
>> incantation only known by the MacRuby/Obj overlords?
>> Thanks,
>> - Matt
>>
>> On Wed, Feb 25, 2009 at 10:13 AM, Brian Chapados <chapbr at gmail.com> wrote:
>>>
>>> CGLRendererInfo is a pointer to a struct:
>>>    typedef struct _CGLRendererInfoObject *CGLRendererInfoObj;
>>>
>>> try creating a pointer to void or to the struct:
>>>
>>> info = Pointer.new_with_type("^v")  # void *info;
>>>
>>> or
>>>
>>> info = Pointer.new_with_type("^{_CGLRendererInfoObject=}") #
>>> CGLRendererInfo *info
>>>
>>> I think the second one is effectively the same as what you were trying
>>> to do with:
>>> info = Pointer.new_with_type("CGLRendererInfoObj")
>>>
>>> except that the runtime doesn't know what to do with
>>> "CGLRendererInfo".  The argument to Pointer.new_with_type must be a
>>> valid Objective-C type encoding[1].
>>>
>>> [1]:
>>> http://developer.apple.com/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/chapter_7_section_1.html#//apple_ref/doc/uid/TP40008048-CH100-SW1
>>>
>>> If you are ever in doubt about what encoding to use, you can always
>>> compile a small Objective-C program that prints out the output of
>>> @encode().  For example:
>>>
>>> #import <Foundation/Foundation.h>
>>> #import <OpenGL/OpenGL.h>
>>>
>>> int main(int argc, char *argv[])
>>> {
>>>    char *encoding = @encode(CGLRendererInfoObj);
>>>    printf("\nencoding => %s\n\n", encoding);
>>>    return 0;
>>> }
>>>
>>> compile with:
>>> gcc -Wall -o encode encode.m -framework Foundation -framework OpenGL
>>>
>>> then run:
>>> ./encode
>>>
>>> Maybe there is an easier way to obtain the output of @encode(). I'm not
>>> sure.
>>>
>>> Brian
>>>
>>> On Wed, Feb 25, 2009 at 1:42 AM, Julien Jassaud <julien at collectapply.jp>
>>> wrote:
>>> > Hello,
>>> > I am trying to port the Cocoa OpenGL sample to MacRuby and encountered a
>>> > few
>>> > problems.
>>> >
>>> > First, I can't access some constants defined in an enum in GLTypes.h. Do
>>> > I
>>> > need to port those constants to ruby by hand ? Is that related
>>> > to gen_bridge_metadata ?
>>> >
>>> > Second, I need to use CGLQueryRendererInfo
>>> > and CGLDescribeRenderer functions. The first one requires a pointer to
>>> > a CGLRendererInfoObj structure but the second requires the object to be
>>> > passed directly. I tried some C style pointer arithmetic :
>>> > info = Pointer.new_with_type("CGLRendererInfoObj")
>>> > count = Pointer.new_with_type("l")
>>> > CGLQueryRendererInfo(caps[:cgl_display_mask], info, count) <- works
>>> > fine,
>>> > but CGLRendererInfoObj is opaque so I can't check it in irb.
>>> > CGLDescribeRenderer(info[0], 0, kCGLRPRendererCount, count) <- I naively
>>> > tried to dereference the pointer, but it doesn't work.
>>> > CGLDescribeRenderer(info, 0, kCGLRPRendererCount, count) <- No
>>> > complaints,
>>> > but the value for count[0] is not consistent (100468704 renderers).
>>> > I see in MacIRB that there is a CGLRendererInfoObj class but I
>>> > can't instantiate it.
>>> > This is all new to me and I may be overlooking something obvious. If
>>> > anyone
>>> > has an idea, please help.
>>> > Thanks,
>>> > Julien Jassaud
>>> > _______________________________________________
>>> > MacRuby-devel mailing list
>>> > MacRuby-devel at lists.macosforge.org
>>> > http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel
>>> >
>>> >
>>> _______________________________________________
>>> MacRuby-devel mailing list
>>> MacRuby-devel at lists.macosforge.org
>>> http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel
>>
>>
>> _______________________________________________
>> MacRuby-devel mailing list
>> MacRuby-devel at lists.macosforge.org
>> http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel
>>
>>
> _______________________________________________
> MacRuby-devel mailing list
> MacRuby-devel at lists.macosforge.org
> http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel
>


More information about the MacRuby-devel mailing list