I'd love to do it in FFI, but getting this far in C was a lot of work! ... so here's another crackpot idea of mine. Another project I have been following is the Pure Language <http://code.google.com/p/pure-lang>. It aims to be a simple, interpreted functional language based on term-rewriting, and also has an LLVM JIT compiler. Using LLVM, they support a literal syntax for declaring foreign functions.
To assist in creating wrappers for libraries, they created a tool called pure-gen that parses C header files and dumps out a .pure file containing FFI declarations. The tool is written in Haskell using a module called Language.C, but I wonder if we could bootstrap something similar by wrapping up Clang's libparse. They've managed to create wrappers for gsl, gtk+ and some other libraries by starting with the generated FFI decls, and adding some syntactic sugar and abstraction within Pure as appropriate. Implementing such a tool is probably going to take a lot of effort, but the benefits are pretty clear – especially since generated wrappers might be usable in JRuby and MRI. I also don't know how much this overlaps with BridgeSupport, but I just wanted to put the idea out there. Best, Jeremy On Thu, May 28, 2009 at 10:38 AM, Matt Aimonetti <mattaimone...@gmail.com> wrote: > I second what Jeremy said. A nice Midi wrapper would be great. > Jeremy, regarding your MusicPlayer lib, the other option is to port it to > FFI and therefore making it JRuby and MacRuby compatible. > > - Matt > > On Thu, May 28, 2009 at 10:32 AM, Jeremy Voorhis <jvoor...@gmail.com> wrote: >> >> Mike, >> >> Is your code available anywhere, e.g. on github? I haven't looked at >> the PyObjC code myself, but I'd be interested in having really decent >> CoreMIDI support available in MacRuby. >> >> Btw, when C extensions are supported, simple apps will be able to use >> my MusicPlayer lib at >> http://github.com/jvoorhis/music_player/tree/master, which wraps much >> of the MusicPlayer/MusicSequence api in AudioToolbox.framework. It's >> short on documentation, but it's easy to get up and running on MRI >> 1.8.x or 1.9.1. >> >> Best, >> >> Jeremy >> >> On Wed, May 27, 2009 at 11:25 PM, Mike Laurence <mklaure...@gmail.com> >> wrote: >> > Hmmm... I'm doing several things different, perhaps one or more of >> > them are impossible :-) >> > >> > Basically, I'm trying to get MIDI support into Ruby via the PYMIDI >> > obj-c library, which is really just a wrapper around CoreMIDI. One way >> > I had thought of: create an additional obj-c class (MidiReceiver) >> > which processes incoming packets for a given MIDI source and then call >> > methods such as "note", "controlChange", "clockTick", etc. This >> > MidiReceiver class can then be overridden by a custom ruby class that >> > contains those same methods. >> > >> > Here is a quick version of the MidiReceiver class (with only the >> > clockTick method for simplicity): >> > >> > ------------- MidiReceiver -------------- >> > >> > #import <MacRuby/MacRuby.h> >> > #include <CoreMIDI/CoreMIDI.h> >> > >> > @interface MidiReceiver : NSObject >> > >> > - (void) processMIDIPacket: (MIDIPacket*) packet; >> > - (void) clockTick; >> > >> > @end >> > >> > @implementation MidiReceiver >> > >> > - (void) processMIDIPacket: (MIDIPacket*) packet { >> > if (packet->length > 0) { >> > >> > int statusByte = packet->data[0]; >> > int status = statusByte >= 0xf0 ? statusByte : statusByte >> 4 << >> > 4; >> > >> > switch (status) { >> > case 0x90: // Note on, etc... >> > case 0xf8: // Clock tick >> > [self performRubySelector:@selector(clockTick)]; >> > break; >> > } >> > } >> > } >> > >> > - (void) clockTick { >> > } >> > >> > @end >> > >> > -------------------------------------------------------- >> > >> > Then, I have a ruby subclass of MidiReceiver that overrides clockTick, >> > etc.: >> > >> > class LiveMidiReceiver < MidiReceiver >> > def clockTick >> > puts "tick!" >> > end >> > end >> > >> > And then, in my Ruby ApplicationController, I'm finding the MIDI >> > source and adding an instance of LiveMidiReceiver as a MIDI receiver: >> > >> > @src = PYMIDIManager.sharedInstance.realSources.find{ |s| >> > s.displayName == 'KONTROL49 PORT A' } >> > receiver = LiveMidiReceiver.new >> > @src.addReceiver(receiver) >> > >> > The LiveMidiReceiver instance, upon receiving a midi packet, is called >> > properly up to the point of the performRubySelector, but thereafter it >> > launches into the debugger with EXC_BAD_ACCESS messages or other >> > unsightly stack dumps. >> > >> > --- >> > >> > An even *better* interface would be to have the "clockTick" and other >> > calls be performable on an arbitrary ruby object without having to >> > subclass MidiReceiver (e.g., have MidiReceiver send "clockTick", etc. >> > to a delegate object which has been created solely in Ruby). I tried >> > that and it gave me similar results, although strangely it only >> > crashed the first time on a clean build - thereafter I saw no crashes, >> > but still no confirmation of ruby method calls either. >> > >> > To test that, I just added a delegate object to MidiReceiver, and then >> > I changed the clockTick recipient from self to delegate: >> > >> > [delegate performRubySelector:@selector(clockTick)]; >> > >> > Then set receiver.delegate = self in my ApplicationController. I'll >> > bet I need some more hooks than that, although it sure would be nice >> > to send ruby messages from obj-c willy-nilly :-) >> > >> > --- >> > >> > I hope I'm making some sense here! I greatly appreciate any info that >> > you can send my way. Hopefully when I get this all figured out I can >> > write a nice, fat blog post about it :-) >> > >> > Regards, >> > Mike Laurence >> > >> > On Wed, May 27, 2009 at 8:18 PM, Laurent Sansonetti >> > <lsansone...@apple.com> wrote: >> >> Hi Mike, >> >> >> >> On May 26, 2009, at 5:45 PM, Mike Laurence wrote: >> >> >> >>> Hello, >> >>> >> >>> I'm trying to get some obj-c code to talk back to my ruby. After >> >>> encountering some "EXC_BAD_ACCESS" messages and scouring the web, I've >> >>> concluded that I'm probably supposed to use performRubySelector >> >>> instead of just expecting selectors to work when overridden by ruby >> >>> subclasses, etc. >> >>> >> >>> What is the preferred way to get this to work? I looked through some >> >>> of Elysium's old code (which used performRubySelector), but I'm having >> >>> trouble wrapping my head around how you're supposed to use the MacRuby >> >>> sharedRuntime to get things to happen. If someone could give me a >> >>> quick example of how to call arbitrary ruby methods, I would highly >> >>> appreciate it. >> >>> >> >>> Of course, if I'm completely off base and there's some other way to >> >>> call ruby code, please let me know! >> >> >> >> Calling Ruby from Objective-C can be problematic, depending if you want >> >> to >> >> call a pure Ruby method or a Ruby method that overrides an Objective-C >> >> one. >> >> If you want to dispatch the method by yourself (and if it's a Ruby >> >> method >> >> that overrides a specialized Objective-C method), you may want to be >> >> very >> >> careful about the types of the arguments you are passing to, as well as >> >> the >> >> return value. >> >> >> >> In any case, using performRubySelector: is better because arguments >> >> will be >> >> converted from Objective-C objects (id) into the expected type, and the >> >> return value will be converted into an Objective-C object. Also, >> >> performRubySelector: can deal with Ruby methods that have optional or >> >> splat >> >> arguments. >> >> >> >> $ cat t.m >> >> #import <Foundation/Foundation.h> >> >> #import <MacRuby/MacRuby.h> >> >> >> >> @interface Foo : NSObject >> >> @end >> >> >> >> @implementation Foo >> >> - (int)aMethodReturningInt >> >> { >> >> return 123; >> >> } >> >> @end >> >> >> >> int main(void) >> >> { >> >> [[MacRuby sharedRuntime] evaluateString:@"class X; def foo(x=1, *a); >> >> p x, >> >> a; end; end"]; >> >> Class k = NSClassFromString(@"X"); >> >> id o = [k new]; >> >> >> >> [o performRubySelector:@selector(foo)]; >> >> [o performRubySelector:@selector(foo:) withArguments:@"1", NULL]; >> >> [o performRubySelector:@selector(foo:) withArguments:@"1", @"2", >> >> @"3", >> >> NULL]; >> >> >> >> [[MacRuby sharedRuntime] evaluateString:@"class Bar < Foo; def >> >> aMethodReturningInt; 42; end; end"]; >> >> k = NSClassFromString(@"Bar"); >> >> o = [k new]; >> >> >> >> NSLog(@"%d", [(Foo *)o aMethodReturningInt]); >> >> NSLog(@"%@", [o >> >> performRubySelector:@selector(aMethodReturningInt)]); >> >> >> >> return 0; >> >> } >> >> $ gcc t.m -o t -framework Foundation -framework MacRuby -fobjc-gc >> >> $ ./t >> >> 1 >> >> [] >> >> "1" >> >> [] >> >> "1" >> >> ["2", "3"] >> >> 2009-05-27 18:16:36.092 t[11922:10b] 42 >> >> 2009-05-27 18:16:36.095 t[11922:10b] 42 >> >> $ >> >> >> >> If you still have problems, it would be easier if you could paste some >> >> code, >> >> this way I can try to help you more. >> >> >> >> HTH, >> >> Laurent >> >> _______________________________________________ >> >> 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 > > _______________________________________________ MacRuby-devel mailing list MacRuby-devel@lists.macosforge.org http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel