How can I use Ruby code in .NET? - c#

I'd like to use a RubyGem in my C# application.
I've downloaded IronRuby, but I'm not sure how to get up and running. Their download includes ir.exe, and it includes some DLLs such as IronRuby.dll.
Once IronRuby.dll is referenced in my .NET project, how do I expose the objects and methods of an *.rb file to my C# code?
Thanks very much,
Michael

This is how you do interop:
Make sure you have refs to IronRuby, IronRuby.Libraries, Microsoft.Scripting and Microsoft.Scripting.Core
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using IronRuby;
using IronRuby.Builtins;
using IronRuby.Runtime;
namespace ConsoleApplication7 {
class Program {
static void Main(string[] args) {
var runtime = Ruby.CreateRuntime();
var engine = runtime.GetRubyEngine();
engine.Execute("def hello; puts 'hello world'; end");
string s = engine.Execute("hello") as string;
Console.WriteLine(s);
// outputs "hello world"
engine.Execute("class Foo; def bar; puts 'hello from bar'; end; end");
object o = engine.Execute("Foo.new");
var operations = engine.CreateOperations();
string s2 = operations.InvokeMember(o, "bar") as string;
Console.WriteLine(s2);
// outputs "hello from bar"
Console.ReadKey();
}
}
}
Note, Runtime has an ExecuteFile which you can use to execute your file.
To get the Gems going
Make sure you install your gem using igem.exe
you will probably have to set some search paths using Engine.SetSearchPaths

Related

Load dynamic delegate function from text file? [duplicate]

I have a WPF C# application that contains a button.
The code of the button click is written in separate text file which will be placed in the applications runtime directory.
I want to execute that code placed in the text file on the click of the button.
Any idea how to do this?
Code sample for executing compiled on fly class method:
using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Net;
using Microsoft.CSharp;
using System.CodeDom.Compiler;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
string source =
#"
namespace Foo
{
public class Bar
{
public void SayHello()
{
System.Console.WriteLine(""Hello World"");
}
}
}
";
Dictionary<string, string> providerOptions = new Dictionary<string, string>
{
{"CompilerVersion", "v3.5"}
};
CSharpCodeProvider provider = new CSharpCodeProvider(providerOptions);
CompilerParameters compilerParams = new CompilerParameters
{GenerateInMemory = true,
GenerateExecutable = false};
CompilerResults results = provider.CompileAssemblyFromSource(compilerParams, source);
if (results.Errors.Count != 0)
throw new Exception("Mission failed!");
object o = results.CompiledAssembly.CreateInstance("Foo.Bar");
MethodInfo mi = o.GetType().GetMethod("SayHello");
mi.Invoke(o, null);
}
}
}
You can use Microsoft.CSharp.CSharpCodeProvider to compile code on-the-fly. In particular, see CompileAssemblyFromFile.
I recommend having a look at Microsoft Roslyn, and specifically its ScriptEngine class.
Here are a few good examples to start with:
Introduction to the Roslyn Scripting API
Using Roslyn ScriptEngine for a ValueConverter to process user input.
Usage example:
var session = Session.Create();
var engine = new ScriptEngine();
engine.Execute("using System;", session);
engine.Execute("double Sin(double d) { return Math.Sin(d); }", session);
engine.Execute("MessageBox.Show(Sin(1.0));", session);
Looks like someone created a library for this called C# Eval.
EDIT: Updated link to point to Archive.org as it seems like the original site is dead.
What you need is a CSharpCodeProvider Class
There are several samples to understand how does it work.
1 http://www.codeproject.com/Articles/12499/Run-Time-Code-Generation-I-Compile-C-Code-using-Mi
The important point of this example that you can do all things on flay in fact.
myCompilerParameters.GenerateExecutable = false;
myCompilerParameters.GenerateInMemory = false;
2 http://www.codeproject.com/Articles/10324/Compiling-code-during-runtime
This example is good coz you can create dll file and so it can be shared between other applications.
Basically you can search for http://www.codeproject.com/search.aspx?q=csharpcodeprovider&x=0&y=0&sbo=kw&pgnum=6 and get more useful links.

Passing lists from IronPython to C# (2)

There's already a similar answered question in this post
but this one is different: I actually do not get a IronPython.Runtime.List (I do have using System.Linq;) from a call like Func<IList<double>> get_a_list = pyOps.GetMember<Func<IList<double>>>(class1, "get_a_list"); where get_a_list is the Python code that returns a Python [] list. I get a {IronPython.Runtime.ListGenericWrapper<double>}. How can I convert that to a C# List?
See the code below - all works fine except for getting the x variable into C#.
class class1(object):
"""Support demo of how to call python from C#"""
def __init__(self):
self.a = 5
def get_a_square(self):
return pow(self.a,2)
def get_a_times_b(self, b):
return self.a*b
def get_a_list(self):
return [self.a,self.a,self.a]
and the C# Code is
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using IronPython.Hosting;
using Microsoft.Scripting.Hosting;
using System.Reflection;
using System.IO;
namespace DemoUsingPythonModule
{
class Program
{
static void Main(string[] args)
{
ScriptEngine pyEngine = Python.CreateEngine();
// Load the DLL and the Python module
Assembly dpma = Asse mbly.LoadFile(Path.GetFullPath("DemoPythonModule.dll"));
pyEngine.Runtime.LoadAssembly(dpma);
ScriptScope pyScope = pyEngine.Runtime.ImportModule("class1");
ObjectOperations pyOps = pyEngine.Operations;
// Instantiate the Python Class
var classObj = pyScope.GetVariable("class1");
object class1 = pyOps.Invoke(classObj);
// Invoke a method of the class
var a2 = pyOps.InvokeMember(class1, "get_a_square", new object[0]);
Console.Write(a2.ToString()+'\n');
// create a callable function to 'get_a_square'
Func<double> get_a_square = pyOps.GetMember<Func<double>>(class1, "get_a_square");
double a2_2 = get_a_square();
// create a callable function to 'get_a_times_b'
Func<double, double> get_a_times_b = pyOps.GetMem ber<Func<double, double>>(class1, "get_a_times_b");
Console.WriteLine(get_a_times_b(3.0).ToString());
Console.WriteLine(get_a_times_b(4.0).ToString());
Func<IList<double>> get_a_list = pyOps.GetMember<Func<IList<double>>>(class1, "get_a_list");
var x = get_a_list();
Console.WriteLine(x.Cast<double>().ToList().ToString());
Console.Write("Press any key to continue . . . ");
Console.ReadKey(true);
}
}
}
OK I found it. The type is indeed IronPython.Runtime.ListGenericWrapper<double> but the Python code above returns a list of ints. If I change the constructor to self.a = 5.0 the thing works.

Would you share your idea how to call python command from embedded Python.Net?

I've been played with Python.Net for a week, but I can't find any sample code to use Python.Net in embedded way although Python.Net source has several embeddeding tests. I've searched many threads from the previous emailing list (Python.Net), the results are not consistent and are clueless.
What I'm trying to do is to get result (PyObject po) from C# code after executing python command such as 'print 2+3' from python prompt via Python.Net because IronPython doesn't have compatibility with the module that I currently using.
When I executed it from nPython.exe, it prints out 5 as I expected. However, when I run this code from embedded way from C#. it returns 'null' always. Would you give me some thoughts how I can get the execution result?
Thank you,
Spark.
Enviroments:
1. Windows 2008 R2, .Net 4.0. Compiled Python.Net with Python27, UCS2 at VS2012
2. nPython.exe works fine to run 'print 2+3'
using NUnit.Framework;
using Python.Runtime;
namespace CommonTest
{
[TestFixture]
public class PythonTests
{
public PythonTests()
{
}
[Test]
public void CommonPythonTests()
{
PythonEngine.Initialize();
IntPtr gs = PythonEngine.AcquireLock();
PyObject po = PythonEngine.RunString("print 2+3");
PythonEngine.ReleaseLock(gs);
PythonEngine.Shutdown();
}
}
}
It seems like PythonEngine.RunString() doesn't work. Instead, PythonEngine.RunSimpleString() works fine.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;
using System.Reflection;
using Python.Runtime;
namespace npythontest
{
public class Program
{
static void Main(string[] args)
{
string external_file = "c:\\\\temp\\\\a.py";
Console.WriteLine("Hello World!");
PythonEngine.Initialize();
IntPtr pythonLock = PythonEngine.AcquireLock();
var mod = Python.Runtime.PythonEngine.ImportModule("os.path");
var ret = mod.InvokeMethod("join", new Python.Runtime.PyString("my"), new Python.Runtime.PyString("path"));
Console.WriteLine(mod);
Console.WriteLine(ret);
PythonEngine.RunSimpleString("import os.path\n");
PythonEngine.RunSimpleString("p = os.path.join(\"other\",\"path\")\n");
PythonEngine.RunSimpleString("print p\n");
PythonEngine.RunSimpleString("print 3+2");
PythonEngine.RunSimpleString("execfile('" + external_file + "')");
PythonEngine.ReleaseLock(pythonLock);
PythonEngine.Shutdown();
}
}
}

Windows 7 clipboard copy paste operation using C#

I'm working on a Windows application where I need to use clipboard data. I am trying to copy text from clipboard by the code below.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
namespace MultiValuedClipBoard
{
class Class1
{
public String SwapClipboardHtmlText(String replacementHtmlText)
{
String returnHtmlText = "hello";
if (Clipboard.ContainsText(TextDataFormat.Html))
{
returnHtmlText = Clipboard.GetText(TextDataFormat.Html);
Clipboard.SetText(replacementHtmlText, TextDataFormat.Html);
}
return returnHtmlText;
}
}
}
Calling the above function by:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Media;
namespace MultiValuedClipBoard
{
class Program
{
static void Main(string[] args)
{
Class1 aas = new Class1();
string a = aas.SwapClipboardHtmlText("chetan");
Console.WriteLine(a);
Console.ReadLine();
}
}
}
When running this code it gives the output "Hello" which is the default value, not clipboard data.
Your code will not work because of two reasons:
[1] When you say:
if (Clipboard.ContainsText(TextDataFormat.Html))
Here you are basically assuming that the clipboard already contains a text and that too in HTML format, but depending on the values you are setting in the clipboard it doesn't look like you are intending to use the pre-existing clipboard value anywhere in your program. So, this if condition should not be there.
[2] Secondly, you are further trying to set the string "chetan" to the clipboard which is definitely not in HTML format. So,
Clipboard.SetText(replacementHtmlText, TextDataFormat.Html);
becomes
Clipboard.SetText(replacementHtmlText, TextDataFormat.Text);
Hence, effectively, your new code becomes something like this:
String returnHtmlText = "hello";
//if (Clipboard.ContainsText(TextDataFormat.Html))
//{
returnHtmlText = Clipboard.GetText(TextDataFormat.Text);
Clipboard.SetText(replacementHtmlText, TextDataFormat.Text);
//}
return returnHtmlText;
Clearly Clipboard.ContainsText(TextDataFormat.Html) evaluates to false. Which means that the clipboard in fact does not contain text in the format you specify.
I changed your program to prove the point:
[STAThread]
static void Main(string[] args)
{
Clipboard.SetText("boo yah!", TextDataFormat.Html);
Class1 aas = new Class1();
string a = aas.SwapClipboardHtmlText("chetan");
Console.WriteLine(a);
Console.WriteLine(Clipboard.GetText(TextDataFormat.Html));
Console.ReadLine();
}
Output:
boo yah!
chetan

execute c# code at runtime from code file

I have a WPF C# application that contains a button.
The code of the button click is written in separate text file which will be placed in the applications runtime directory.
I want to execute that code placed in the text file on the click of the button.
Any idea how to do this?
Code sample for executing compiled on fly class method:
using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Net;
using Microsoft.CSharp;
using System.CodeDom.Compiler;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
string source =
#"
namespace Foo
{
public class Bar
{
public void SayHello()
{
System.Console.WriteLine(""Hello World"");
}
}
}
";
Dictionary<string, string> providerOptions = new Dictionary<string, string>
{
{"CompilerVersion", "v3.5"}
};
CSharpCodeProvider provider = new CSharpCodeProvider(providerOptions);
CompilerParameters compilerParams = new CompilerParameters
{GenerateInMemory = true,
GenerateExecutable = false};
CompilerResults results = provider.CompileAssemblyFromSource(compilerParams, source);
if (results.Errors.Count != 0)
throw new Exception("Mission failed!");
object o = results.CompiledAssembly.CreateInstance("Foo.Bar");
MethodInfo mi = o.GetType().GetMethod("SayHello");
mi.Invoke(o, null);
}
}
}
You can use Microsoft.CSharp.CSharpCodeProvider to compile code on-the-fly. In particular, see CompileAssemblyFromFile.
I recommend having a look at Microsoft Roslyn, and specifically its ScriptEngine class.
Here are a few good examples to start with:
Introduction to the Roslyn Scripting API
Using Roslyn ScriptEngine for a ValueConverter to process user input.
Usage example:
var session = Session.Create();
var engine = new ScriptEngine();
engine.Execute("using System;", session);
engine.Execute("double Sin(double d) { return Math.Sin(d); }", session);
engine.Execute("MessageBox.Show(Sin(1.0));", session);
Looks like someone created a library for this called C# Eval.
EDIT: Updated link to point to Archive.org as it seems like the original site is dead.
What you need is a CSharpCodeProvider Class
There are several samples to understand how does it work.
1 http://www.codeproject.com/Articles/12499/Run-Time-Code-Generation-I-Compile-C-Code-using-Mi
The important point of this example that you can do all things on flay in fact.
myCompilerParameters.GenerateExecutable = false;
myCompilerParameters.GenerateInMemory = false;
2 http://www.codeproject.com/Articles/10324/Compiling-code-during-runtime
This example is good coz you can create dll file and so it can be shared between other applications.
Basically you can search for http://www.codeproject.com/search.aspx?q=csharpcodeprovider&x=0&y=0&sbo=kw&pgnum=6 and get more useful links.

Categories