rubydotnet-developer Mailing List for rubydotnet (Page 3)
Status: Alpha
Brought to you by:
thomas
You can subscribe to this list here.
2003 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
(26) |
Aug
(3) |
Sep
(41) |
Oct
(1) |
Nov
|
Dec
|
---|---|---|---|---|---|---|---|---|---|---|---|---|
2004 |
Jan
(6) |
Feb
|
Mar
|
Apr
(2) |
May
(1) |
Jun
(3) |
Jul
(3) |
Aug
(2) |
Sep
|
Oct
(3) |
Nov
|
Dec
|
From: Ben S. <bsc...@pr...> - 2003-09-07 22:22:54
|
Hi Thomas, We had similar feelings about the default binder, its functionality, and = its private-ness. What we've done is to delegate to the default binder instead of inherit = from its class. We do parameter conversions when necessary - almost = exactly like your pseudocode! - and then ask the default binder if it = can find a match. The binder interface provides us with a list of = possible matches, so we do loop over all of them looking for a = conversion set that allows the default binder to bind something (if that = makes sense). If you have any questions about the above or other aspects of the = binding - please ask! Regards, Ben -----Original Message----- From: Thomas Sondergaard [mailto:th...@th...] Sent: Sun 9/7/2003 9:56 AM To: rub...@li... Cc:=09 Subject: [Rubydotnet-developer] System.Reflection.Binder Hi guys, I've been doing things a little backwards and I've now got interface implementation from ruby running. I've also got the code ready for = creating a delegate from a proc, but I'm still missing the plumming to use it. = I'm wondering how to automatically convert proc objects into the appropriate Delegate type. Type.InvokeMember uses a System.Reflection.Binder object = to do the actual binding, so I could subclass Binder and have it do it. Unfortunately you cannot subclass the default binder and I'm not keen on having to replicate whatever functionality is in it, especially as I = don't really know all of what it does. How have you gone about this problem? I wish there was a way to add specific parameter conversions that would = be allowed during member resolution and binding, without having to = sacrifice the properties of the default binder. All I really want is that during parameter matching, the following would be considered (pseudo code) if (requiredParameterType is a delegateType && actualParameter is IProc) convertedParameter =3D = TypedDelegateFactory.create(requiredParameterType, actualParameter, "call') (Type TypedDelegateFactory.create(Type delegateType, IObject obj, string methodName) is the bit I've already got) Suggestions? Cheers, Thomas ------------------------------------------------------- This sf.net email is sponsored by:ThinkGeek Welcome to geek heaven. http://thinkgeek.com/sf _______________________________________________ Rubydotnet-developer mailing list Rub...@li... https://lists.sourceforge.net/lists/listinfo/rubydotnet-developer |
From: Thomas S. <th...@th...> - 2003-09-07 13:56:45
|
Hi guys, I've been doing things a little backwards and I've now got interface implementation from ruby running. I've also got the code ready for creating a delegate from a proc, but I'm still missing the plumming to use it. I'm wondering how to automatically convert proc objects into the appropriate Delegate type. Type.InvokeMember uses a System.Reflection.Binder object to do the actual binding, so I could subclass Binder and have it do it. Unfortunately you cannot subclass the default binder and I'm not keen on having to replicate whatever functionality is in it, especially as I don't really know all of what it does. How have you gone about this problem? I wish there was a way to add specific parameter conversions that would be allowed during member resolution and binding, without having to sacrifice the properties of the default binder. All I really want is that during parameter matching, the following would be considered (pseudo code) if (requiredParameterType is a delegateType && actualParameter is IProc) convertedParameter = TypedDelegateFactory.create(requiredParameterType, actualParameter, "call') (Type TypedDelegateFactory.create(Type delegateType, IObject obj, string methodName) is the bit I've already got) Suggestions? Cheers, Thomas |
From: Thomas S. <th...@th...> - 2003-09-06 13:31:13
|
> The magic is that the .NET runtime requires netmodules to be in the same > location as the dll (or .so) files, not in the ruby\bin folder. This, of > course, is highly desirable. Thanks, that did the job! Cheers, Thomas |
From: John R. P. <jo...@pi...> - 2003-09-06 12:59:07
|
On Sat, 6 Sep 2003 12:58:55 +0200, "Thomas Sondergaard" wrote: > I have a problem that I hope you guys can help me with. The > DynamicLanguageSupport.dll is now needed by my dotnet.so, but I need to put > the DynamicLanguageSupport.dll next to the ruby.exe binary otherwise it > isn't found. > > Any suggestions? Sure, we had the same issue and corrected it by building the .NET dll instead as a netmodule. If you check out our project we have a batch routine that runs the following command: csc /nologo /d:TRACE /t:module /out:ext\DotNetBridge.Core.so ..\Core\*.cs Of course, you would use the appropriate compiler for the language you've written you're DynamicLanguageSupport in, but get it build as a module. The magic is that the .NET runtime requires netmodules to be in the same location as the dll (or .so) files, not in the ruby\bin folder. This, of course, is highly desirable. Hope that helps, John |
From: Thomas S. <th...@th...> - 2003-09-06 10:58:56
|
> It would be fine with us for you to use that code under Ruby's license. Thanks for asking! > > If you could attribute it to us, that would be great as well. (If such attribution is awkward or > inappropriate in your environment - that is OK too.) Great thanks. I have taken the emit code in your DynamicDelegate and created a DynamicLanguageSupport.dll library that given a dynamic object interface: public interface IObject { public object send(string message, object[]args); } Can generate appropriate delegate and class types using these two interfaces public class DynamicDelegateFactory { public static Delegate create(Type delegateType, IObject o, string message); } You can also create the appropriate wrapper object for ruby instances using public class DynamicClassFactory { // creates a subclass of baseType (which must implement IObject above) // that implements the interfaces in interfaces public static Type getType(Type baseType, Type[] interfaces); } I'm thinking this is just an example of code that is useful for any dynamic scripting language that wants to interop with .net, so I have extracted it into a separate project (cvs.sf.net:/cvsroot/rubydotnet co misc/DynamicLanguageSupport). I have a problem that I hope you guys can help me with. The DynamicLanguageSupport.dll is now needed by my dotnet.so, but I need to put the DynamicLanguageSupport.dll next to the ruby.exe binary otherwise it isn't found. Any suggestions? Cheers, Thomas |
From: Ben S. <bsc...@pr...> - 2003-09-05 20:06:49
|
Hi Thomas, > When I presented the rationale for starting my own project I=20 > neglected to > mention that I'm working on an article describing the use of=20 > managed C++ to > implement a ruby/.net interop solution. Until I'm further=20 > along with the > article I'll be working in my own sandbox. >=20 > As for SCM it is not important which system it is, as long as it is > available freely (as in beer). >=20 > Oh, I also wanted to ask John and Ben whether it would be=20 > okay if I borrowed > a bit of code from your DynamicDelegate class. My extension=20 > module uses the > ruby license which is more liberal than GPL. It would be fine with us for you to use that code under Ruby's license. = Thanks for asking! If you could attribute it to us, that would be great as well. (If such = attribution is awkward or inappropriate in your environment - that is OK = too.) We may, but haven't yet, release the entire program under a more liberal = license in the future. We chose GPL for the initial releases largely = because it was familiar to us and seemed acceptable for the time being. Please keep all of us posted on how your article and implementation are = going - maybe we can collaborate more closely as things progress! Regards, Ben Schroeder |
From: Thomas S. <th...@th...> - 2003-09-05 14:30:56
|
> Agreed. So what would make working with our project easier? We have released > the source code in the distribution. As for SCM, we currently have the source > code in a private Perforce Depot. I made arrangements with Perforce for this > open source project and got free licenses to run this project on Perforce. The > Perforce depot could be opened up to other developers. I tend to like Perforce > more than CVS, anyways. Is the fact that we use Perforce instead of CVS a big > deal to you? > When I presented the rationale for starting my own project I neglected to mention that I'm working on an article describing the use of managed C++ to implement a ruby/.net interop solution. Until I'm further along with the article I'll be working in my own sandbox. As for SCM it is not important which system it is, as long as it is available freely (as in beer). Oh, I also wanted to ask John and Ben whether it would be okay if I borrowed a bit of code from your DynamicDelegate class. My extension module uses the ruby license which is more liberal than GPL. Cheers, Thomas |
From: John R. P. <jo...@pi...> - 2003-09-04 15:28:02
|
On Thu, 4 Sep 2003 16:56:55 +0200, "Thomas Sondergaard" wrote: > > Does this mean a joint effort is slipping away from all of us? R2 of our > bridge > > includes a C++ extension module as well in approx 300 lines of code (if > that is > > a measure of something). Additionally, we also have approx. 250 automated > unit > > tests using TestUnit for both the socket and direct C++ versions of the > bridge. > > > > Not necessarily. I started my own little project because the threshold to > getting started on the two existing projects was a little high. I needed to > get some basic understanding of the ruby extension model and managed C++ > first and besides none of the existing projects had public CVS access to the > latest and greatest making it impossible to contribute. Even if our efforts > are separate and uncoordinated there are still bits and pieces that can > easily be transferred from one project to the other if we agree to do so. Agreed. So what would make working with our project easier? We have released the source code in the distribution. As for SCM, we currently have the source code in a private Perforce Depot. I made arrangements with Perforce for this open source project and got free licenses to run this project on Perforce. The Perforce depot could be opened up to other developers. I tend to like Perforce more than CVS, anyways. Is the fact that we use Perforce instead of CVS a big deal to you? Regards, John |
From: Thomas S. <th...@th...> - 2003-09-04 14:57:05
|
> Does this mean a joint effort is slipping away from all of us? R2 of our bridge > includes a C++ extension module as well in approx 300 lines of code (if that is > a measure of something). Additionally, we also have approx. 250 automated unit > tests using TestUnit for both the socket and direct C++ versions of the bridge. > Not necessarily. I started my own little project because the threshold to getting started on the two existing projects was a little high. I needed to get some basic understanding of the ruby extension model and managed C++ first and besides none of the existing projects had public CVS access to the latest and greatest making it impossible to contribute. Even if our efforts are separate and uncoordinated there are still bits and pieces that can easily be transferred from one project to the other if we agree to do so. > I like this -- didn't know it was a new feature of module in 1.8. Can you do it > without the "include <namespace>" line? We really like that our bridge flattens > the .NET namespaces (but we can still use the FQN if necessary). No, you don't have to include System::Collections, I just did that in the example to show that you can do it, just as you can with native ruby modules. The trick is the on-demand discovery of classes and namespace which saves time at start-up and (a lot) of memory without loosing the ruby-look-and-feel :-). Once discovered the namespace (represented by an empty ruby module) or class is assigned to a constant the same way as ruby works itself. Cheers, Thomas |
From: Ben S. <bsc...@pr...> - 2003-09-04 13:17:30
|
Adding to what John wrote ... > > Have you made any progress on the thread safety issue with=20 > callbacks from > > .net to ruby? I'm wondering if it is necessary to make some kind of > > synchronized queue, where you post you callbacks and then=20 > have a pool of > > ruby threads reading the jobs from that queue as they are=20 > posted. Or maybe > > we could lobby match to add some locking to ruby to make it=20 > thread-safe? I > > know too little about this :-)=20 >=20 > Yep! You are right! Our socket edition of the bridge=20 > handles this correctly > and utilizes a message queue concept. We call the concept=20 > the Post Office in > our classes in the code. Callbacks are handled and posted on=20 > the correct thread > in Ruby and/or .NET. As an aside, we have yet to make our=20 > C++ extension follow > this same behavior. If you're interested, the tests in "Ruby/tests/TestRubySideQueueing.rb" = from our download test the Ruby PostOffice. Threads send socket = messages and then call PostOffice#waitForResult; a receiving thread then = calls #returnResult, #throwException, or #runOnThreadWithId to tell the = waiting thread what to do next. There are similar tests on the .NET side at = "Tests/PostOfficeTesting.cs". The code has some cosmetic differences = between the two sides - which might be nice to iron out - but is = similar. (Our latest release can be found at = "http://www.saltypickle.com/rubydotnet/Downloads".) I'm not sure whether the tests are in great shape for reading - but I'd = be happy to answer any questions! Regards, Ben |
From: John R. P. <jo...@pi...> - 2003-09-04 12:32:03
|
> Hi, > > I've made some progress with my own rubydotnet project. Instead of using > sockets for communication or hosting the CLR, my module is written as a > managed C++ extension. With this approach I have managed to get the basic > functionality running with 245 lines of C++ code and 50 lines of ruby. Does this mean a joint effort is slipping away from all of us? R2 of our bridge includes a C++ extension module as well in approx 300 lines of code (if that is a measure of something). Additionally, we also have approx. 250 automated unit tests using TestUnit for both the socket and direct C++ versions of the bridge. > One of the things that I have done differently is the class discovery. > Instead of using a DotNet object as root for the hierarchy I'm using the new > Module#const_missing feature in ruby-1.8.0, which means that I can do > something like this: > > require 'dotnet' > include System.Collections > > a = ArrayList.new > > a.count # => 0 > a.add(1) > a.count # => 1 I like this -- didn't know it was a new feature of module in 1.8. Can you do it without the "include <namespace>" line? We really like that our bridge flattens the .NET namespaces (but we can still use the FQN if necessary). > I've also got a Kernel::reference() method you can call to reference > whatever assemblies you may want to use. Again, nice trick. I like it. > I'm worried about .net class inheritance from ruby, though, from a garbage > collection stand point. When I pass a ruby object to .net I wrap it in a > RubyDotNet::Object .net wrapper and vice versa with .net objects that are > passed to ruby. These wrappers lock the wrapped objects from being garbage > collected using rb_gc_register_address on the ruby side an > System::Runtime::InteropServices::GCHandle on the .net side. If you inherit > a .net class from ruby you will need the ruby object and the .net object to > reference each-other, but then they will be locked in memory and will never > be garbage collected. I'm aware that this is just a special case of a cyclic > reference problem that exists with my approach, but it is not too likely to > bite you in most other cases. We took the approach in the first two releases of our bridge that GC is not high on our list. If we are a leaky until process exit occurs, well, we can still get a lot of work done. We will address GC issues in upcoming releases of our bridge. > How have you guys addressed this problem? Do you have any idea about how to > handle this problem? Technically, I'd look to break the cycle you mention by using a WeakReference on one side or the other of the interop. I don't know if that is possible, but that is what I'd search for. I believe both Ruby and .NET have WeakReference concepts, but I could be wrong. > Have you made any progress on the thread safety issue with callbacks from > .net to ruby? I'm wondering if it is necessary to make some kind of > synchronized queue, where you post you callbacks and then have a pool of > ruby threads reading the jobs from that queue as they are posted. Or maybe > we could lobby match to add some locking to ruby to make it thread-safe? I > know too little about this :-) Yep! You are right! Our socket edition of the bridge handles this correctly and utilizes a message queue concept. We call the concept the Post Office in our classes in the code. Callbacks are handled and posted on the correct thread in Ruby and/or .NET. As an aside, we have yet to make our C++ extension follow this same behavior. Regards, John |
From: Thomas S. <th...@th...> - 2003-09-03 21:16:55
|
This is a repost as my first email seems to have dissappeared. If you got the first one, please ignore this one :-) Hi, I've made some progress with my own rubydotnet project. Instead of using sockets for communication or hosting the CLR, my module is written as a managed C++ extension. With this approach I have managed to get the basic functionality running with 245 lines of C++ code and 50 lines of ruby. One of the things that I have done differently is the class discovery. Instead of using a DotNet object as root for the hierarchy I'm using the new Module#const_missing feature in ruby-1.8.0, which means that I can do something like this: require 'dotnet' include System.Collections a = ArrayList.new a.count # => 0 a.add(1) a.count # => 1 I've also got a Kernel::reference() method you can call to reference whatever assemblies you may want to use. Next I'll add delegates that invoke ruby and.net interface implementation in ruby. This should be relatively straightforward. I'm worried about .net class inheritance from ruby, though, from a garbage collection stand point. When I pass a ruby object to .net I wrap it in a RubyDotNet::Object .net wrapper and vice versa with .net objects that are passed to ruby. These wrappers lock the wrapped objects from being garbage collected using rb_gc_register_address on the ruby side an System::Runtime::InteropServices::GCHandle on the .net side. If you inherit a .net class from ruby you will need the ruby object and the .net object to reference each-other, but then they will be locked in memory and will never be garbage collected. I'm aware that this is just a special case of a cyclic reference problem that exists with my approach, but it is not too likely to bite you in most other cases. How have you guys addressed this problem? Do you have any idea about how to handle this problem? Have you made any progress on the thread safety issue with callbacks from .net to ruby? I'm wondering if it is necessary to make some kind of synchronized queue, where you post you callbacks and then have a pool of ruby threads reading the jobs from that queue as they are posted. Or maybe we could lobby match to add some locking to ruby to make it thread-safe? I know too little about this :-) Cheers, Thomas |
From: Tim S. <ti...@ih...> - 2003-08-26 05:48:55
|
On Mon, Aug 25, 2003 at 04:35:06PM -0700, John R. Pierce wrote: > Hi Thomas, > > Hope you are rested from your long vacation. As for the collaboration of > RubyDotNet development, up to this point, the collaboration has been merely a > sharing of code bases and developing some rudimentary documentation. Tim > Sutherland released his rubydotnet proxy code on this list and Ben and myself > have released our Ruby/.NET Bridge on www.saltypickle.com/rubydotnet. [...] Hi. Note that the release I made to this list was completely broken. I'll be releasing an unbroken version soon - I just need to fix one bug :) |
From: John R. P. <jo...@pi...> - 2003-08-25 23:35:10
|
Hi Thomas, Hope you are rested from your long vacation. As for the collaboration of RubyDotNet development, up to this point, the collaboration has been merely a sharing of code bases and developing some rudimentary documentation. Tim Sutherland released his rubydotnet proxy code on this list and Ben and myself have released our Ruby/.NET Bridge on www.saltypickle.com/rubydotnet. That has been the extent of the collaboration -- more introductions than anything. What do you suggest as a way to get off the ground here? Ben Schroeder and myself are very interested in advancing our Ruby/.NET bridge more and would welcome any help. I also would love to incorporate Tim Sutherland's ideas, but I think being the fact there are two code bases being developed, this could be the first sticking point for getting a collaboration off the ground. As for what we've done with our Ruby/.NET bridge, we have release 2 coming out this week that will include a Squeak Smalltalk interface to the bridge (really slick!), floating point type conversion between Ruby and .NET, and a Ruby C extension module that shows 3 - 4 times performance improvement over the TCP socket edition of the bridge that we've developed up to this point. We do have some threading issues to work out with the C extension that are presently being handled correctly in the TCP sockets edition, but I think we will release anyways. Check out our site as to what we are thinking next for the project (our To Do page). If any of those tasks sounds immediately interesting then let's chat more -- we'd be curious as to where you'd want to take the bridge as well and how you could assist. Regards, John ----------------------------------------- On Mon, 25 Aug 2003 11:10:35 +0200, "Thomas Sondergaard" wrote: > > Hello, > > I have returned from my long vacation and I want to start working on > rubydotnet! :-) Before I start another separate effort I'd like to hear if > any of the existing efforts would welcome my contribution. I remember there > are two or three separate groups working on a ruby extension module and I > think we should consider uniting our efforts. > > I really think it is a waste of effort to have so many separate efforts when > we could easily work together! > > What are your thoughts on this? > > Thomas > > > > > > ------------------------------------------------------- > This SF.net email is sponsored by: VM Ware > With VMware you can run multiple operating systems on a single machine. > WITHOUT REBOOTING! Mix Linux / Windows / Novell virtual machines > at the same time. Free trial click here:http://www.vmware.com/wl/offer/358/0 > _______________________________________________ > Rubydotnet-developer mailing list > Rub...@li... > https://lists.sourceforge.net/lists/listinfo/rubydotnet-developer |
From: Thomas S. <th...@th...> - 2003-08-25 10:37:00
|
Hello, I have returned from my long vacation and I want to start working on rubydotnet! :-) Before I start another separate effort I'd like to hear if any of the existing efforts would welcome my contribution. I remember there are two or three separate groups working on a ruby extension module and I think we should consider uniting our efforts. I really think it is a waste of effort to have so many separate efforts when we could easily work together! What are your thoughts on this? Thomas |
From: Ben S. <bsc...@pr...> - 2003-07-28 19:42:30
|
I am pleased to announce Release 1 of Ben Schroeder's and John Pierce's = Ruby/.NET Bridge. A zip file containing the release is available at http://www.saltypickle.com/RubyDotNet/Downloads Installation instructions can be found in the download as well as at http://www.saltypickle.com/RubyDotNet/Installation More information is available at A guide to using the Ruby/.NET Bridge http://www.saltypickle.com/RubyDotNet/Guide The Ruby/.NET bridge Swiki http://www.saltypickle.com/RubyDotNet We're looking forward to hearing all of your thoughts. Please ask if = you have any questions on installation, usage, etc. - the documentation = should be a good start, but it is fairly incomplete. I apologize for the delay in releasing this - I know it's about a week = later than I had thought. :) Regards, Ben Schroeder |
From: John R. P. <jo...@pi...> - 2003-07-23 11:05:17
|
Yes, I am using the pragprog dist of Ruby (1.6.8) and I am successfully building the direct dotnet extensions using VS.NET 2003. I do have to slip in a compiler switch to permit me to include the CLR, but that's only if you really need to include .NET in your ruby C extension. Regards, John On Wed, 23 Jul 2003 08:10:33 +0100, "Thomas Sondergaard" wrote: > > Do any of you guys know whether you can build ruby extension modules with > Visual Studio .net, or do you need Visual Studio/C++ 6.0? I'd be building > them to be used with the pragprog ruby dist for windows. > > Cheers, > > Thomas > > > ------------------------------------------------------- > This SF.net email is sponsored by: VM Ware > With VMware you can run multiple operating systems on a single machine. > WITHOUT REBOOTING! Mix Linux / Windows / Novell virtual machines at the > same time. Free trial click here: http://www.vmware.com/wl/offer/345/0 > _______________________________________________ > Rubydotnet-developer mailing list > Rub...@li... > https://lists.sourceforge.net/lists/listinfo/rubydotnet-developer |
From: Tim S. <ti...@ih...> - 2003-07-23 07:24:57
|
On Wed, Jul 23, 2003 at 08:10:33AM +0100, Thomas Sondergaard wrote: > Do any of you guys know whether you can build ruby extension modules with > Visual Studio .net, or do you need Visual Studio/C++ 6.0? I'd be building > them to be used with the pragprog ruby dist for windows. Don't know, but I've successfully used mingw/msys. |
From: Thomas S. <th...@th...> - 2003-07-23 07:10:49
|
Do any of you guys know whether you can build ruby extension modules with Visual Studio .net, or do you need Visual Studio/C++ 6.0? I'd be building them to be used with the pragprog ruby dist for windows. Cheers, Thomas |
From: Ben S. <bsc...@pr...> - 2003-07-22 13:20:18
|
Hi John, all, > At least this is how we've approached our development of our=20 > Ruby.NET bridge to > date. Now what I think would be interesting is to develop=20 > some sort of runtime > wrapper technology for .NET to be able to call ruby classes=20 > that implement a > certain interface. This would be less an exercise in=20 > annotating a ruby class > and generating an assembly at "compile time" and more an=20 > issue of generating a > .net wrapper of the Ruby class at runtime (emit the IL) based=20 > upon interface > signatures. It occurs to me that, if we had this technology, we could use it to = create new Ruby types for people to consume, if we were willing to do = separate compilation. We would just create the .NET interface in its = own assembly and then write a Ruby class to implement it. Over the long run, or if I was doing a lot of consuming of new Ruby = types from .NET, I think I would prefer something like Richard = describes, as it keeps the declarations near the code. The = implementation-from-Ruby code could be extended to create the new = interface assembly from the extern declarations. Regards, Ben Schroeder |
From: Richard K. <ri...@in...> - 2003-07-22 03:44:29
|
I would agree that the priority is Ruby scripting .NET classes, in the same way that Ruby driving a WSDL/SOAP services has high value. The question becomes when will we be able to have Ruby produce services (webservices or Types) to be consumed by others. Again, this is less important right now, but is important in the long run IMHO. -rich On Monday, July 21, 2003, at 10:57 PM, Thomas Sondergaard wrote: > The type declarations would only be necessary if you wanted to define > new > types in ruby and make them available to other .net classes. With the > type |
From: John R. P. <jo...@pi...> - 2003-07-22 03:23:11
|
Got it. I agree -- this is interesting, but lower on my priority list as well. I was discussing this topic today with my colleague, Ben Schroeder, and we both felt, that while it is interesting and more complete to let .NET classes call out to Ruby classes, we see a ton more value in our day-to-day activities to let Ruby script control .NET classes. At least this is how we've approached our development of our Ruby.NET bridge to date. Now what I think would be interesting is to develop some sort of runtime wrapper technology for .NET to be able to call ruby classes that implement a certain interface. This would be less an exercise in annotating a ruby class and generating an assembly at "compile time" and more an issue of generating a .net wrapper of the Ruby class at runtime (emit the IL) based upon interface signatures. For example, imagine you have a .net class that collects classes that implement ILoggable. So you want your Ruby class to implement ILoggable at runtime so you can slip it into the .NET collection. Under this scenario, the interop would generate a wrapper at runtime that calls back to the ruby methods that implement that interface (ILoggable). All of this could be done without any annotation of Ruby code. We do the same thing right now in our Ruby.Net bridge, but only for delegates (which is essentially an interface with one method). Regards, John With that said, this doesn't mean that we don't want to go the other way On Tue, 22 Jul 2003 03:57:09 +0100, "Thomas Sondergaard" wrote: > > The type declarations would only be necessary if you wanted to define new > types in ruby and make them available to other .net classes. With the type > annotations you could run a utility, lets call it genWrapperAssembly.rb, that > loads your ruby library and generates a .net assembly defining .net wrappers > for all your the ruby types. These wrappers would then call into ruby. This > would be a useful addition to the interop/bridge at some point, but it is not > high on my own priority list. After all, it is possible to do subclassing and > interface implementation without doing any of this - it is only if you want > to define new types in ruby. > > Cheers > > Thomas > > > ---------- Original Message ----------- > From: "John R. Pierce" <jo...@pi...> > To: rub...@li... > Sent: Mon, 21 Jul 2003 08:29:06 -0700 (PDT) > Subject: Re: [Rubydotnet-developer] Getting necessary metadata on Ruby > classes for externalization... > > > I'd have to see the .NET calling code to help me see how annotating the > > parameter types enables the bridge to work or work better than not > annotating > > param types. > > > > I can see how one would need to annotate the return type so that as > > the method returns out of Ruby I don't always have to downcast the > > return type from object to whatever, but, when it comes to sending > > parameters, ruby doesn't care if it gets an object type and, > > generally, I don't see the need to enforce a compiler check on > > parameter types. That's what unit tests are for. > > > > Regards, > > > > John > > > > On Fri, 18 Jul 2003 23:54:29 -0400, Richard Kilmer wrote: > > > > > > > > All, > > > > > > I did not quite know where to post this, and I hope this list is ok... > > > > > > I have been thinking a bit on how to allow a developer to annotate > > > their class's methods with parameter types when used externally by > > > statically typed languages (Java, C#, SOAP). I want to present a > > > syntax, and at the bottom have the code to back it up. > > > > > > Given the following class: > > > > > > class Account > > > def Account.open(first, last) > > > end > > > def close > > > end > > > def add(money) > > > end > > > def remove(money) > > > end > > > def transfer(money, account) > > > end > > > end > > > > > > And assuming you wanted to make that accessible for statically typed > > > systems you would just do this: > > > > > > require 'extern' > > > > > > class Account > > > extern :Account.open, :return[Account], :first[String], :last[String] > > > def Account.open(first, last) > > > end > > > > > > extern :close > > > def close > > > end > > > > > > extern :add, :money[Float] > > > def add(money) > > > end > > > > > > extern :remove, :money[Float] > > > def remove(money) > > > end > > > > > > extern :transfer, :money[Float], :account[Account] > > > def transfer(money, account) > > > end > > > end > > > > > > So, for each method you want to externalize you just include the > > > 'extern' call. > > > > > > Usage: extern <method symbol>, [ [<:return[Classname]>], > > > <:param[Classname]>, ... ] > > > > > > To reflect on this metadata you do: > > > > > > Account.each_externalized_method do | method | > > > puts method.to_s > > > end > > > > > > Which outputs: > > > > > > Account Account.open(String first, String last) > > > NilClass close() > > > NilClass add(Float money) > > > NilClass remove(Float money) > > > NilClass transfer(Float money, Account account) > > > > > > You can, of course, inspect the method (ExternalMethodDefinition > > > instance) instead of printing it out. So this creates a runtime > > > structure to store type information about methods, which again is > > > useful is you want to bridge .NET to Ruby at the level of having a CLR > > > type subclass a Ruby class, or generate a CLR type that represents a > > > Ruby class. > > > > > > Of course, since Ruby's classes are open, you can define this extern > > > metadata on existing classes: > > > > > > class ThreadGroup > > > extern :ThreadGroup.new, :return[ThreadGroup] > > > extern :add, :return[ThreadGroup], :thread[Thread] > > > extern :list, :return[Array] > > > end > > > > > > So what do folks think about the syntax? > > > > > > -rich > > > > > > PS...here is the magic code that makes this syntax work: > > > > > > ________ BEGIN 'extern.rb' _________ > > > > > > class ExternalMethodDefinition > > > attr_accessor :klass, :name, :return_type > > > Parameter = Struct.new(:name, :type) > > > @@definitions = Hash.new([]) > > > > > > def self.[](klass) > > > @@definitions[klass] > > > end > > > > > > def initialize(klass, name, *parameters) > > > list = @@definitions[klass] > > > unless list > > > list = [] > > > @@defintions[klass] = list > > > end > > > list << self > > > @klass = klass > > > @name = name.to_s > > > @name.gsub!(/__/, '.') > > > @parameters = [] > > > parameters.each do |param| > > > if param.name=="return" > > > @return_type = param.type > > > else > > > @parameters << param > > > end > > > end > > > @return_type = NilClass unless @return_type > > > end > > > > > > def add_parameter(name, type) > > > unless type.kind_of?(Class) > > > raise "Parameter #{name}'s type on method '#{@name}' of class > > > '#{@klass}' must be a Ruby class" > > > end > > > if name == :return > > > @return_type = type > > > else > > > @parameters << Parameter.new(name.to_s, type) > > > end > > > end > > > > > > def each_parameter > > > @parameters.each {|param| yield param} > > > end > > > > > > def to_s > > > params = (@parameters.collect {|param| param.type.to_s+' > > > '+param.name}).join(', ') > > > return "#{@return_type.to_s} #{@name}(#{params})" > > > end > > > end > > > > > > class Symbol > > > def [](klass=nil) > > > if klass > > > ExternalMethodDefinition::Parameter.new(self.to_s, klass) > > > else > > > (self.to_s+"__[]").intern > > > end > > > end > > > > > > def method_missing(method, *args, &block) > > > if (?A..?Z).member?(self.to_s[0]) > > > return (self.to_s+"__"+method.to_s).intern > > > end > > > super > > > end > > > end > > > > > > class Module > > > def extern(method, *parameters) > > > ExternalMethodDefinition.new(self, method, *parameters) > > > end > > > > > > def each_externalized_method > > > ExternalMethodDefinition[self].each { |exdef| yield exdef } > > > end > > > end > > > > > > ------ END 'extern.rb' ------ > > > > > > > > > > > > ------------------------------------------------------- > > > This SF.net email is sponsored by: VM Ware > > > With VMware you can run multiple operating systems on a single machine. > > > WITHOUT REBOOTING! Mix Linux / Windows / Novell virtual machines at the > > > same time. Free trial click here: http://www.vmware.com/wl/offer/345/0 > > > _______________________________________________ > > > Rubydotnet-developer mailing list > > > Rub...@li... > > > https://lists.sourceforge.net/lists/listinfo/rubydotnet-developer > > > > ------------------------------------------------------- > > This SF.net email is sponsored by: VM Ware > > With VMware you can run multiple operating systems on a single machine. > > WITHOUT REBOOTING! Mix Linux / Windows / Novell virtual machines at the > > same time. Free trial click here: > > http://www.vmware.com/wl/offer/345/0 > _______________________________________________ > > Rubydotnet-developer mailing list > > Rub...@li... > > https://lists.sourceforge.net/lists/listinfo/rubydotnet-developer > ------- End of Original Message ------- > > > > ------------------------------------------------------- > This SF.net email is sponsored by: VM Ware > With VMware you can run multiple operating systems on a single machine. > WITHOUT REBOOTING! Mix Linux / Windows / Novell virtual machines at the > same time. Free trial click here: http://www.vmware.com/wl/offer/345/0 > _______________________________________________ > Rubydotnet-developer mailing list > Rub...@li... > https://lists.sourceforge.net/lists/listinfo/rubydotnet-developer |
From: Thomas S. <th...@th...> - 2003-07-22 02:57:25
|
The type declarations would only be necessary if you wanted to define new types in ruby and make them available to other .net classes. With the type annotations you could run a utility, lets call it genWrapperAssembly.rb, that loads your ruby library and generates a .net assembly defining .net wrappers for all your the ruby types. These wrappers would then call into ruby. This would be a useful addition to the interop/bridge at some point, but it is not high on my own priority list. After all, it is possible to do subclassing and interface implementation without doing any of this - it is only if you want to define new types in ruby. Cheers Thomas ---------- Original Message ----------- From: "John R. Pierce" <jo...@pi...> To: rub...@li... Sent: Mon, 21 Jul 2003 08:29:06 -0700 (PDT) Subject: Re: [Rubydotnet-developer] Getting necessary metadata on Ruby classes for externalization... > I'd have to see the .NET calling code to help me see how annotating the > parameter types enables the bridge to work or work better than not annotating > param types. > > I can see how one would need to annotate the return type so that as > the method returns out of Ruby I don't always have to downcast the > return type from object to whatever, but, when it comes to sending > parameters, ruby doesn't care if it gets an object type and, > generally, I don't see the need to enforce a compiler check on > parameter types. That's what unit tests are for. > > Regards, > > John > > On Fri, 18 Jul 2003 23:54:29 -0400, Richard Kilmer wrote: > > > > > All, > > > > I did not quite know where to post this, and I hope this list is ok... > > > > I have been thinking a bit on how to allow a developer to annotate > > their class's methods with parameter types when used externally by > > statically typed languages (Java, C#, SOAP). I want to present a > > syntax, and at the bottom have the code to back it up. > > > > Given the following class: > > > > class Account > > def Account.open(first, last) > > end > > def close > > end > > def add(money) > > end > > def remove(money) > > end > > def transfer(money, account) > > end > > end > > > > And assuming you wanted to make that accessible for statically typed > > systems you would just do this: > > > > require 'extern' > > > > class Account > > extern :Account.open, :return[Account], :first[String], :last[String] > > def Account.open(first, last) > > end > > > > extern :close > > def close > > end > > > > extern :add, :money[Float] > > def add(money) > > end > > > > extern :remove, :money[Float] > > def remove(money) > > end > > > > extern :transfer, :money[Float], :account[Account] > > def transfer(money, account) > > end > > end > > > > So, for each method you want to externalize you just include the > > 'extern' call. > > > > Usage: extern <method symbol>, [ [<:return[Classname]>], > > <:param[Classname]>, ... ] > > > > To reflect on this metadata you do: > > > > Account.each_externalized_method do | method | > > puts method.to_s > > end > > > > Which outputs: > > > > Account Account.open(String first, String last) > > NilClass close() > > NilClass add(Float money) > > NilClass remove(Float money) > > NilClass transfer(Float money, Account account) > > > > You can, of course, inspect the method (ExternalMethodDefinition > > instance) instead of printing it out. So this creates a runtime > > structure to store type information about methods, which again is > > useful is you want to bridge .NET to Ruby at the level of having a CLR > > type subclass a Ruby class, or generate a CLR type that represents a > > Ruby class. > > > > Of course, since Ruby's classes are open, you can define this extern > > metadata on existing classes: > > > > class ThreadGroup > > extern :ThreadGroup.new, :return[ThreadGroup] > > extern :add, :return[ThreadGroup], :thread[Thread] > > extern :list, :return[Array] > > end > > > > So what do folks think about the syntax? > > > > -rich > > > > PS...here is the magic code that makes this syntax work: > > > > ________ BEGIN 'extern.rb' _________ > > > > class ExternalMethodDefinition > > attr_accessor :klass, :name, :return_type > > Parameter = Struct.new(:name, :type) > > @@definitions = Hash.new([]) > > > > def self.[](klass) > > @@definitions[klass] > > end > > > > def initialize(klass, name, *parameters) > > list = @@definitions[klass] > > unless list > > list = [] > > @@defintions[klass] = list > > end > > list << self > > @klass = klass > > @name = name.to_s > > @name.gsub!(/__/, '.') > > @parameters = [] > > parameters.each do |param| > > if param.name=="return" > > @return_type = param.type > > else > > @parameters << param > > end > > end > > @return_type = NilClass unless @return_type > > end > > > > def add_parameter(name, type) > > unless type.kind_of?(Class) > > raise "Parameter #{name}'s type on method '#{@name}' of class > > '#{@klass}' must be a Ruby class" > > end > > if name == :return > > @return_type = type > > else > > @parameters << Parameter.new(name.to_s, type) > > end > > end > > > > def each_parameter > > @parameters.each {|param| yield param} > > end > > > > def to_s > > params = (@parameters.collect {|param| param.type.to_s+' > > '+param.name}).join(', ') > > return "#{@return_type.to_s} #{@name}(#{params})" > > end > > end > > > > class Symbol > > def [](klass=nil) > > if klass > > ExternalMethodDefinition::Parameter.new(self.to_s, klass) > > else > > (self.to_s+"__[]").intern > > end > > end > > > > def method_missing(method, *args, &block) > > if (?A..?Z).member?(self.to_s[0]) > > return (self.to_s+"__"+method.to_s).intern > > end > > super > > end > > end > > > > class Module > > def extern(method, *parameters) > > ExternalMethodDefinition.new(self, method, *parameters) > > end > > > > def each_externalized_method > > ExternalMethodDefinition[self].each { |exdef| yield exdef } > > end > > end > > > > ------ END 'extern.rb' ------ > > > > > > > > ------------------------------------------------------- > > This SF.net email is sponsored by: VM Ware > > With VMware you can run multiple operating systems on a single machine. > > WITHOUT REBOOTING! Mix Linux / Windows / Novell virtual machines at the > > same time. Free trial click here: http://www.vmware.com/wl/offer/345/0 > > _______________________________________________ > > Rubydotnet-developer mailing list > > Rub...@li... > > https://lists.sourceforge.net/lists/listinfo/rubydotnet-developer > > ------------------------------------------------------- > This SF.net email is sponsored by: VM Ware > With VMware you can run multiple operating systems on a single machine. > WITHOUT REBOOTING! Mix Linux / Windows / Novell virtual machines at the > same time. Free trial click here: > http://www.vmware.com/wl/offer/345/0 _______________________________________________ > Rubydotnet-developer mailing list > Rub...@li... > https://lists.sourceforge.net/lists/listinfo/rubydotnet-developer ------- End of Original Message ------- |
From: John R. P. <jo...@pi...> - 2003-07-21 15:29:13
|
I'd have to see the .NET calling code to help me see how annotating the parameter types enables the bridge to work or work better than not annotating param types. I can see how one would need to annotate the return type so that as the method returns out of Ruby I don't always have to downcast the return type from object to whatever, but, when it comes to sending parameters, ruby doesn't care if it gets an object type and, generally, I don't see the need to enforce a compiler check on parameter types. That's what unit tests are for. Regards, John On Fri, 18 Jul 2003 23:54:29 -0400, Richard Kilmer wrote: > > All, > > I did not quite know where to post this, and I hope this list is ok... > > I have been thinking a bit on how to allow a developer to annotate > their class's methods with parameter types when used externally by > statically typed languages (Java, C#, SOAP). I want to present a > syntax, and at the bottom have the code to back it up. > > Given the following class: > > class Account > def Account.open(first, last) > end > def close > end > def add(money) > end > def remove(money) > end > def transfer(money, account) > end > end > > And assuming you wanted to make that accessible for statically typed > systems you would just do this: > > require 'extern' > > class Account > extern :Account.open, :return[Account], :first[String], :last[String] > def Account.open(first, last) > end > > extern :close > def close > end > > extern :add, :money[Float] > def add(money) > end > > extern :remove, :money[Float] > def remove(money) > end > > extern :transfer, :money[Float], :account[Account] > def transfer(money, account) > end > end > > So, for each method you want to externalize you just include the > 'extern' call. > > Usage: extern <method symbol>, [ [<:return[Classname]>], > <:param[Classname]>, ... ] > > To reflect on this metadata you do: > > Account.each_externalized_method do | method | > puts method.to_s > end > > Which outputs: > > Account Account.open(String first, String last) > NilClass close() > NilClass add(Float money) > NilClass remove(Float money) > NilClass transfer(Float money, Account account) > > You can, of course, inspect the method (ExternalMethodDefinition > instance) instead of printing it out. So this creates a runtime > structure to store type information about methods, which again is > useful is you want to bridge .NET to Ruby at the level of having a CLR > type subclass a Ruby class, or generate a CLR type that represents a > Ruby class. > > Of course, since Ruby's classes are open, you can define this extern > metadata on existing classes: > > class ThreadGroup > extern :ThreadGroup.new, :return[ThreadGroup] > extern :add, :return[ThreadGroup], :thread[Thread] > extern :list, :return[Array] > end > > So what do folks think about the syntax? > > -rich > > PS...here is the magic code that makes this syntax work: > > ________ BEGIN 'extern.rb' _________ > > class ExternalMethodDefinition > attr_accessor :klass, :name, :return_type > Parameter = Struct.new(:name, :type) > @@definitions = Hash.new([]) > > def self.[](klass) > @@definitions[klass] > end > > def initialize(klass, name, *parameters) > list = @@definitions[klass] > unless list > list = [] > @@defintions[klass] = list > end > list << self > @klass = klass > @name = name.to_s > @name.gsub!(/__/, '.') > @parameters = [] > parameters.each do |param| > if param.name=="return" > @return_type = param.type > else > @parameters << param > end > end > @return_type = NilClass unless @return_type > end > > def add_parameter(name, type) > unless type.kind_of?(Class) > raise "Parameter #{name}'s type on method '#{@name}' of class > '#{@klass}' must be a Ruby class" > end > if name == :return > @return_type = type > else > @parameters << Parameter.new(name.to_s, type) > end > end > > def each_parameter > @parameters.each {|param| yield param} > end > > def to_s > params = (@parameters.collect {|param| param.type.to_s+' > '+param.name}).join(', ') > return "#{@return_type.to_s} #{@name}(#{params})" > end > end > > class Symbol > def [](klass=nil) > if klass > ExternalMethodDefinition::Parameter.new(self.to_s, klass) > else > (self.to_s+"__[]").intern > end > end > > def method_missing(method, *args, &block) > if (?A..?Z).member?(self.to_s[0]) > return (self.to_s+"__"+method.to_s).intern > end > super > end > end > > class Module > def extern(method, *parameters) > ExternalMethodDefinition.new(self, method, *parameters) > end > > def each_externalized_method > ExternalMethodDefinition[self].each { |exdef| yield exdef } > end > end > > ------ END 'extern.rb' ------ > > > > ------------------------------------------------------- > This SF.net email is sponsored by: VM Ware > With VMware you can run multiple operating systems on a single machine. > WITHOUT REBOOTING! Mix Linux / Windows / Novell virtual machines at the > same time. Free trial click here: http://www.vmware.com/wl/offer/345/0 > _______________________________________________ > Rubydotnet-developer mailing list > Rub...@li... > https://lists.sourceforge.net/lists/listinfo/rubydotnet-developer |
From: Thomas S. <th...@th...> - 2003-07-21 14:29:07
|
> So what do folks think about the syntax? I'd prefer the syntax to be as terse as possible and with as little duplicate information as possible. In other words, I'd prefer extern :Account.open, Account, String, String def Account.open(first, last) end to extern :Account.open, :return[Account], :first[String], :last[String] def Account.open(first, last) end But I don't know how to get the names of the arguments? The Module methods to iterate over methods simply return strings. So I'm not sure we can do better, than what you suggest, and it's not bad at all, but maybe we should suggest to matz that it would be convenient if you could get more information at runtime about the signature of a method? Cheers, Thomas ---------- Original Message ----------- From: Richard Kilmer <ri...@in...> To: rub...@li... Sent: Fri, 18 Jul 2003 23:54:29 -0400 Subject: [Rubydotnet-developer] Getting necessary metadata on Ruby classes for externalization... > All, > > I did not quite know where to post this, and I hope this list is ok... > > I have been thinking a bit on how to allow a developer to annotate > their class's methods with parameter types when used externally by > statically typed languages (Java, C#, SOAP). I want to present a > syntax, and at the bottom have the code to back it up. > > Given the following class: > > class Account > def Account.open(first, last) > end > def close > end > def add(money) > end > def remove(money) > end > def transfer(money, account) > end > end > > And assuming you wanted to make that accessible for statically typed > systems you would just do this: > > require 'extern' > > class Account > extern :Account.open, :return[Account], :first[String], :last[String] > def Account.open(first, last) > end > > extern :close > def close > end > > extern :add, :money[Float] > def add(money) > end > > extern :remove, :money[Float] > def remove(money) > end > > extern :transfer, :money[Float], :account[Account] > def transfer(money, account) > end > end > > So, for each method you want to externalize you just include the > 'extern' call. > > Usage: extern <method symbol>, [ [<:return[Classname]>], > <:param[Classname]>, ... ] > > To reflect on this metadata you do: > > Account.each_externalized_method do | method | > puts method.to_s > end > > Which outputs: > > Account Account.open(String first, String last) > NilClass close() > NilClass add(Float money) > NilClass remove(Float money) > NilClass transfer(Float money, Account account) > > You can, of course, inspect the method (ExternalMethodDefinition > instance) instead of printing it out. So this creates a runtime > structure to store type information about methods, which again is > useful is you want to bridge .NET to Ruby at the level of having a > CLR type subclass a Ruby class, or generate a CLR type that > represents a Ruby class. > > Of course, since Ruby's classes are open, you can define this extern > metadata on existing classes: > > class ThreadGroup > extern :ThreadGroup.new, :return[ThreadGroup] > extern :add, :return[ThreadGroup], :thread[Thread] > extern :list, :return[Array] > end > > So what do folks think about the syntax? > > -rich > > PS...here is the magic code that makes this syntax work: > > ________ BEGIN 'extern.rb' _________ > > class ExternalMethodDefinition > attr_accessor :klass, :name, :return_type > Parameter = Struct.new(:name, :type) > @@definitions = Hash.new([]) > > def self.[](klass) > @@definitions[klass] > end > > def initialize(klass, name, *parameters) > list = @@definitions[klass] > unless list > list = [] > @@defintions[klass] = list > end > list << self > @klass = klass > @name = name.to_s > @name.gsub!(/__/, '.') > @parameters = [] > parameters.each do |param| > if param.name=="return" > @return_type = param.type > else > @parameters << param > end > end > @return_type = NilClass unless @return_type > end > > def add_parameter(name, type) > unless type.kind_of?(Class) > raise "Parameter #{name}'s type on method '#{@name}' of class > '#{@klass}' must be a Ruby class" > end > if name == :return > @return_type = type > else > @parameters << Parameter.new(name.to_s, type) > end > end > > def each_parameter > @parameters.each {|param| yield param} > end > > def to_s > params = (@parameters.collect {|param| param.type.to_s+' > '+param.name}).join(', ') > return "#{@return_type.to_s} #{@name}(#{params})" > end > end > > class Symbol > def [](klass=nil) > if klass > ExternalMethodDefinition::Parameter.new(self.to_s, klass) > else > (self.to_s+"__[]").intern > end > end > > def method_missing(method, *args, &block) > if (?A..?Z).member?(self.to_s[0]) > return (self.to_s+"__"+method.to_s).intern > end > super > end > end > > class Module > def extern(method, *parameters) > ExternalMethodDefinition.new(self, method, *parameters) > end > > def each_externalized_method > ExternalMethodDefinition[self].each { |exdef| yield exdef } > end > end > > ------ END 'extern.rb' ------ > > ------------------------------------------------------- > This SF.net email is sponsored by: VM Ware > With VMware you can run multiple operating systems on a single machine. > WITHOUT REBOOTING! Mix Linux / Windows / Novell virtual machines at the > same time. Free trial click here: > http://www.vmware.com/wl/offer/345/0 _______________________________________________ > Rubydotnet-developer mailing list > Rub...@li... > https://lists.sourceforge.net/lists/listinfo/rubydotnet-developer ------- End of Original Message ------- |