How to get a variable from Python file using IronPython - c#

I want to get a variable from my Python file and write it in the console
here is what i have tried:
main.py
myVar = "Hello There"
program.cs
using System;
using IronPython.Hosting;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
var py = Python.CreateEngine();
var pythonVariable = py.ExecuteFile("main.py");
Console.WriteLine(pythonVariable);
Console.Read();
}
}
}
I would expect the output to be 'Hello There' but I get this: 'Microsoft.Scripting.Hosting.ScriptScope'

The output you get is hinting what you have to look for. ExecuteFile returns a ScriptScope which contains all the variables defined in the executed Python code.
In order to retrieve a specific variable from it you need to use GetVariable or TryGetVariable (if the variable may not exist in the file), e.g.:
using System;
using IronPython.Hosting;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
var py = Python.CreateEngine();
var pythonVariable = py.ExecuteFile("main.py").GetVariable<string>("myVar");
Console.WriteLine(pythonVariable);
Console.Read();
}
}
}
Note that I used the generic version of GetVariable to convert it to a string immediately. The non-generic version returns a dynamic object, choosing which one you need depends on how you intend to use the variable

Follow this procedure and it should work, Be sure to have file in the right place. I don't see you setting any variables Do that and just follow the code:
var engine = Python.CreateEngine(); // Extract Python language engine from their grasp
var source = engine.CreateScriptSourceFromFile(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "myPython.py"));
var scope = engine.CreateScope();
source.Execute(scope);
var theVar = scope.GetVariable("myVar");
Console.WriteLine(theVar);
Console.ReadKey();

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.

Change application type with Mono.Cecil?

How can I modify an application from Console Application Type to Windows Application Type and vice versa with Mono.Cecil?
To convert a console .exe to windows .exe, you can use:
var file = "foo.exe";
var module = ModuleDefinition.ReadModule (file);
// module.Kind was previously ModuleKind.Console
module.Kind = ModuleKind.Windows;
module.Write (file);
The other way around is as simple as choosing the appropriate ModuleKind value. From Cecil's source:
public enum ModuleKind {
Dll,
Console,
Windows,
NetModule,
}
For people who needed more help on this like me :)
you may need the apt pacakge libmono-cecil-cil-dev
//mono-cecil-set-modulekind-windows.cs
using System;
using Mono.Cecil;
namespace CecilUtilsApp {
class CecilUtils {
static void Main(string[] args) {
var file = args[0];
var module = ModuleDefinition.ReadModule (file);
module.Kind = ModuleKind.Windows;
module.Write (file);
}
}
}
// -----
//Makefile
//mono-cecil-set-modulekind-eq-windows.exe:
// mcs $(shell pkg-config --libs mono-cecil) ./mono-cecil-set-modulekind-windows.cs
./mono-cecil-set-modulekind-windows.exe myprog.exe

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.

How can I use Ruby code in .NET?

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

Categories