Works beautifully!

Oct 1, 2013 at 10:17 PM
Edited Oct 1, 2013 at 10:20 PM
This works absolutely beautifully.

Here is the R code for a simple "hello world" project:
# http://r2clr.codeplex.com/
# Install from .zip file
library(rClr)
clrLoadAssembly('H:/Cs/FromR/bin/Debug/FromR.dll')
myObj <- clrNew('FromR.Class,FromR')
x <- clrCall(myObj, 'GetName')
x
[1] "Hello world"
y <- clrCall(myObj, 'GetArray')
y
[1] 0 1 2 3 4 5 6 7
Here is the accompanying C# code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace FromR
{
    public class Class
    {
        public string GetName()
        {
            return "Hello world";
        }

        public double[] GetArray()
        {
            return new double[] { 0,1,2,3,4,5,6,7};
        }
    }
}
Note that if you want to recompile the .dll, you have to exit R first to remove the lock on the .dll. It would be great if the .dll didn't have a lock, and there was some way to reload the .dll within R. Its actually impossible to unload a C# .dll from memory within C#, so this would probably require tearing down the CLR and starting it again.
Coordinator
Oct 2, 2013 at 8:25 AM
Thanks a lot for the positive feedback.

I noted the feature request for loading/unloading a DLL without a restart of R : https://rclr.codeplex.com/workitem/5

Some years ago I worked on a plug-in system, but indeed once loaded, it could not be unloaded (probably with reasons). I also encountered some logical but seriously non-intuitive behaviors with multiple load contexts (forgot the details actually), so for rClr I deliberately chose to go with using a single ApplicationDomain and load context to start with, to not end up with some very confused users if they bump in these behaviors, however unlikely.

I am curious as to whether the CLR can be reinitialized; I think I read somewhere that the hosted MS CLR could not be reinitialised twice, but I lost the reference to this.

Feel free to report experience, question and use cases here or in the new web site.

Regards
Oct 2, 2013 at 5:24 PM

Great to hear from you. If there is anything I can do to help the project, please let me know.

It's possible to use shadow dlls so that the .dll is not locke on load, and the project can be recompiled. Its probably also possible to make a local copy of the .dll and load that instead.

An app domain is like a process, if you tear it down everything inside it will disappear. I think that would be the easiest way to reload the .dll.

However, I'm just stoked to finally be able to use C# in R. Although allowing reloading would shorten the development cycle as it woildnt require a restart of R, I'm very happy with the current release, thanks again!

May 18, 2014 at 3:52 PM
Hi there,

I just wanted to say a big "thanks" for all the work you're putting into R.NET.

Really, really nice work, you have my utmost respect!
Aug 13, 2014 at 5:13 AM
Hi Gravitas,

Thanks for your work. I followed your code with an argument. Please check below code.
But I can't call GetName(0) or GetName(n). Would you help me?

** R code
> detach("package:rClr", unload=TRUE)
> library(rClr)
Loading the dynamic library for Microsoft .NET runtime...
Loaded Common Language Runtime version 4.0.30319.18444

> clrLoadAssembly('C:/Working/GA_test/Hello3/r2clr_TEST_HelloWorld.dll')
> myObj <- clrNew('r2clr_TEST_HelloWorld.Class,r2clr_TEST_HelloWorld')
> clrCall(myObj, 'GetArray')
[1] 0 1 2 3 4 5 6 7
> clrCall(myObj, 'GetName(0)')
Error in clrCall(myObj, "GetName(0)") : 
  Type:    System.MissingMethodException
Message: Could not find method GetName(0) on object
Method:  System.Object CallInstanceMethod(System.Object, System.String, System.Object[])
Stack trace:
   at Rclr.ClrFacade.CallInstanceMethod(Object obj, String methodName, Object[] arguments) in f:\codeplex\r2clr\packages\rClr\src\ClrFacade\ClrFacade.cs:line 34

> clrCall(myObj, 'GetName',1)
Error in clrCall(myObj, "GetName", 1) : 
  Type:    System.MissingMethodException
Message: Could not find method GetName on object
Method:  System.Object CallInstanceMethod(System.Object, System.String, System.Object[])
Stack trace:
   at Rclr.ClrFacade.CallInstanceMethod(Object obj, String methodName, Object[] arguments) in f:\codeplex\r2clr\packages\rClr\src\ClrFacade\ClrFacade.cs:line 34
** c# code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace r2clr_TEST_HelloWorld
{
    public class Class
    {
        public string GetName(int _arg)
        {
            string outSTR = "";
            if (_arg == 0)
                outSTR = "My Name is Zero.";
            else
                outSTR = "My name is Notzero";

            return outSTR;
        }

        public double[] GetArray()
        {
            return new double[] { 0, 1, 2, 3, 4, 5, 6, 7 };
        }
    }
}
Regards, Neo
Coordinator
Aug 13, 2014 at 5:26 AM
Hi Neo,

you need to call using clrCall(myObj, 'GetName',1L) to match the .NET integer type.

This is because a sole alphanumeric in R is not an integer be default.
> str(1)
 num 1
> str(1L)
 int 1
In passing, oddly:
> str(1:1)
 int 1
rClr in development now has better error messages for these situations, perhaps automatic type cast for some unambiguous cases.
Aug 13, 2014 at 5:48 AM
Hi Jperraud,

Thanks a lot for my taking a quantum leap in R. I got output below.
> detach("package:rClr", unload=TRUE)
Error in detach("package:rClr", unload = TRUE) : invalid 'name' argument
> library(rClr)
Loading the dynamic library for Microsoft .NET runtime...
Loaded Common Language Runtime version 4.0.30319.18444

> clrLoadAssembly('C:/Working/GA_test/Hello3/r2clr_TEST_HelloWorld.dll')
> myObj <- clrNew('r2clr_TEST_HelloWorld.Class,r2clr_TEST_HelloWorld')
> clrCall(myObj, 'GetName', 1L)
[1] "My name is Notzero"
> clrCall(myObj, 'GetName', 0L)
[1] "My Name is Zero."
> 
Regards, Neo
Aug 13, 2014 at 9:40 PM
Great to see that everything is working. R.NET really is a work of genius.