From: Eric Schwartz Date: 2002-11-09T03:33:37+09:00 Subject: Extending ruby with mixed C/ruby classes? I'd like to extend Ruby to directly interface with STAF (http://staf.sf.net/), which I'm using to actually execute my tests, and report on their status. STAF has a C API, and I think I understand how to wrap it with Ruby, but I have a few questions on that. Just FYI, the only reference I've found so far is the online Pickaxe; other pointers are welcome, so long as they are available online (offline refs are welcome too, but I'd like to finish this today if possible; it doesn't seem to be THAT hard, and I'm getting excited enough about Ruby that I want to start USING it, darn it!). Also, I would like to define a few Ruby classes as well, to make exception handling a little easier. I've included a sort of psuedocode for how I'd write the whole thing in ruby below. The issues I have are: 1) I'm reading the Pickaxe example, and it seems to match my situation quit nicely-- STAF has a STAFHandle_t type that connects the client with the server, and is passed as a parameter to all other calls. So I want to wrap that up in a STAFHandle class (I'm naming the class that way to match the C++ and Java interfaces; I'm going to compose that into a STAFCommand class that operates like a File). So far, so good, but when I read the Pickaxe, it shows the CDPlayer class defining an 'initialize' method (good, I get that) and a 'new' Singleton method. What?!? I'm perfectly willing to concede that I don't understand Ruby's concept of Singleton methods, but why doesn't the example just create the CDJukebox * and call Data_Wrap_Struct() on it in the initialize() function? Why do it that way? And, of course, do I need to mirror that structure in my code? 2) How do I structure my code so that I can keep STAFResult and STAFException as pure Ruby classes, and just create and/or raise them from the STAFHandle class? I saw all sorts of examples of how to create Strings, Arrays, and Hashes, in C code, but nothing about how to create some generic Ruby class in a C method. Assuming I have STAFHandle.c, STAFResult.rb and STAFException.rb in the same directory, how can I create a STAFResult object in STAFHandle.c? Am I correct in assuming that I'd use the same method to create a STAFException (or some appropriate subclass), and then call 'rb_raise(cExceptionInstance, "Appropriate text")'? Thanks for your help-- I had initially thought Ruby a solution in search of a problem, but all of a sudden, everything's starting to look OO again, and it's a happy feeling. Any help you can give in getting me out of this quandry is greatly appreciated. -=Eric ---- file 'STAFResult.rb' ----- module STAF class STAFResult def initialize(rc, result) @rc = rc; @result = result attr_reader :rc, :result end end ----- end 'STAFResult.rb' ----- ---- file 'STAFHandle.rb' ----- require 'stafresult' module STAF class STAFHandle def initialize(name) @handle = # do stuff to initialize "@handle" with 'name' end def submit(machine, service, request) retval = # do stuff to submit a 'request' to 'service' on 'machine' # retval is a STAFResult end def STAFHandle.formatString(format, args...) # format a string here end def STAFHandle.wrapData(string) # quote the string in a way STAF likes end end end ----- end 'STAFHandle.rb' ----- ---- file 'STAFException.rb' ---- module STAF class STAFException < Exception def initalize(rc,text,name='STAFException') super(text) @rc = rc @name = name end def to_s puts "Caught STAFException" puts "Name : #{@name}" puts "Location : #{backtrace()[0]}" puts "Text : #{message()}" puts "Error code: #{@rc} end end class STAFOutOfBoundsException < Exception def initialize(rc, text) super(rc, text, "STAFOutOfBoundsException"); end end class STAFInvalidObjectException < Exception def initialize(rc, text) super(rc, text, "STAFInvalidObjectException"); end end class STAFInvalidParmException < Exception def initialize(rc, text) super(rc, text, "STAFInvalidParmException"); end end class STAFBaseOSErrorException < Exception def initialize(rc, text) super(rc, text, "STAFBaseOSErrorException"); end end end ----- end 'STAFException.rb' ---- -- Come to think of it, there are already a million monkeys on a million typewriters, and Usenet is NOTHING like Shakespeare. -- Blair Houghton