[MacRuby-devel] Porting Cocoa OpenGL sample code

Laurent Sansonetti lsansonetti at apple.com
Wed Feb 25 14:10:00 PST 2009


That's a pretty good idea. I tried to make the Pointer class as simple  
(and stupid) as possible but we might need some convenience APIs on  
top of it, for those not familiar with the Objective-C encoding types.

Here is an API proposal based on Brian's snippet... thoughts?

class Pointer
   def self.new(type='@')
     new_with_type(type)
   end
   TYPES = {
    :int => 'i',
    :uint => 'I',
    ...
   }
   def self.to(sym)
     new_with_type(TYPES[sym])
   end
   def value
     self[0]
   end
end

# I'm pretty sure I already wrote something similar in RubyCocoa.

Laurent

On Feb 25, 2009, at 1:16 PM, Matt Aimonetti wrote:

> 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
>>
> _______________________________________________
> 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