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.

Comments (5)

  1. Kris says:

    The power of invoking dynamic language from C#/Java can be  demonstrated by showing an application which can take plugins/extensions written in Python/Ruby. I have yet to see a solid example of this. The other approac which I have seen is where you expose a server product's API to be configurable by dynamic languages.  Websphere takes this approach (uses Jython).

  2. ASP.NET How to use the IHttpAsyncHandler in ASP.NET [Via: Mads Kristensen ] SQL Server SQL SERVER -...

  3. Normal 0 false false false EN-US X-NONE X-NONE MicrosoftInternetExplorer4 /* Style Definitions */ table.MsoNormalTable

  4. Computer Help says:

    Really great information, has given me an idea for a blog of my friends.

  5. Andrius Bentkus says:

    Nice, but what if the function has no return type? Func<void> is not valid...

Skip to main content