How to invoke a IronPython function from C# using the DLR Hosting API
Like I wrote in my previous post, the Hosting API lets you do some very interesting and powerful things with the DLR. One of the things I had listed was the ability to invoke a method implemented in python from C#.
This post describes how to set up the VS IDE and the DLR binaries to create an extremely basic DLR host. So if you are new to DLR you may want to quickly go over the step-by-step procedure to get your dev environment set up.
Here's what you would have to do
1. Create the ScriptRuntime object and get the python engine associated with it
ScriptEngine pyEng = ScriptRuntime.Create().GetEngine("python");
2. Implement a function in python and create a ScriptSource object based on the python code
string pyFunc = @"def isodd(n): return 1 == n % 2;";
ScriptSource source = pyEng.CreateScriptSourceFromString(pyFunc,
SourceCodeKind.Statements);
3. Create a ScriptScope object. This object will act as the context for the python code.
ScriptScope scope = pyEng.CreateScope();
4. Execute the ScriptSource object in the context of the ScriptScope object created in step (3).
source.Execute(scope);
5. From C#, Use the 'GetVariable' method in the ScriptScope to get the delegate to the python function implemented in step 2. ( The GetVariable method lets you access any variable defined in python from C# or VB or any other managed language)
Func<int, bool> IsOdd = scope.GetVariable<Func<int, bool>>("isodd");
6. Invoke the delegate.
bool b = IsOdd(1);
The above steps can be used to invoke any non instance method in python from C#. Instance members can be invoked using a similary but slightly different technique. (I will put up a sample that explains this shortly)
You can find more details about the methods and classes used in this sample in the Hosting API Spec.
Here’s the full sample program.
using System;
using System.Scripting;
using Microsoft.Scripting.Hosting;
namespace ConsoleApplication1 {
class Program {
static void Main(string[] args) {
//create a runtime and get the python engine
ScriptEngine pyEng = ScriptRuntime.Create().GetEngine("python");
//implement a python function and create a ScriptSource object out of it
string pyFunc = @"def isodd(n): return 1 == n % 2;";
ScriptSource source = pyEng.CreateScriptSourceFromString(pyFunc,
SourceCodeKind.Statements);
//create a scope to act as the context for the code
ScriptScope scope = pyEng.CreateScope();
//execute the source
source.Execute(scope);
//get a delegate to the python function
Func<int, bool> IsOdd = scope.GetVariable<Func<int, bool>>("isodd");
//invoke the delegate
Console.WriteLine(IsOdd(1));
Console.WriteLine(IsOdd(2));
}
}
}
I hope you find this sample useful. I am planning to post a series of articles on DLR Hosting along similar lines( How To's, step-by-step guides etc). It would be very helpful to get your feedback regarding this. So please leave a comment if you have any questions, suggestions or other feedback.