[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