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@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@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@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@lists.macosforge.org
http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel


_______________________________________________
MacRuby-devel mailing list
MacRuby-devel@lists.macosforge.org
http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel


_______________________________________________
MacRuby-devel mailing list
MacRuby-devel@lists.macosforge.org
http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel


_______________________________________________
MacRuby-devel mailing list
MacRuby-devel@lists.macosforge.org
http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel