Thread: Re: [Rubydotnet-developer] rubydotnet - first announcement
Status: Alpha
Brought to you by:
thomas
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: 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 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-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: 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-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: 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 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: 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 |