[MacRuby-devel] Porting Cocoa OpenGL sample code
Brian Chapados
chapbr at gmail.com
Wed Feb 25 12:43:20 PST 2009
> 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
>
>
More information about the MacRuby-devel
mailing list