[MacRuby-devel] Porting Cocoa OpenGL sample code

Julien Jassaud sojastar07 at gmail.com
Fri Feb 27 08:57:53 PST 2009


Brian,

Thanks for the very detailed answer. This tremendously helps. I am now  
having problems with arrays, though. I try to make a pointer to an  
array of 32 longs, like this :

 >> p = Pointer.new_with_type('[32L]')
=> #<Pointer:0x80052af00>
 >> p[0]
ArgumentError: can't convert C/Objective-C value `0x80052ae40' of type  
`[32i]' to Ruby object
	from (irb):49:in `[]'
	from (irb):49
	from /usr/local/bin/macirb:12:in `<main>'

Am I not getting the syntax explained in the documentation page you  
mentioned ?

Also, something is puzzling me. In C, arrays are pointers so I thought  
I could solve the problem (and it works) by doing :

 >> p=Pointer.new_with_type('^L')
=> #<Pointer:0x800530380>
 >> p.assign([1,2,3])
=> [1, 2, 3]
 >> p[0][1]
=> 2

Great ! I have a pointer to something that looks like an array of  
longs (and it seems to satisfy the CGGetActiveDisplayList function).  
But how is it possible when everything here is an object and not a  
series of neatly aligned bytes ?

Anyway, you are right. The part of Cocoa OpenGL I am porting now  
probably doesn't need to and should be wrapped in an Objective-C object.

Thanks,
Julien Jassaud

Le 26 févr. 09 à 05:43, Brian Chapados a écrit :

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

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-devel/attachments/20090228/e6c33e5d/attachment-0001.html>


More information about the MacRuby-devel mailing list