Calling IronPython functions from .NET

Having worked with Python in the past I find IronPython an interesting language to work with. However the story becomes really interesting if you can combine IronPython with regular strong typed code into one.

So I decided to take a look at what it would take to do so with the current IronPython version. I used IronPython 2 Beta 3, based upon the current version of the Dynamic Language Runtime, which is still evolving so the classes might have changed, take care! You can download the latest IronPython release here.

 

Lets take a look at what it takes to use an IronPython class from a Visual Basic Project.

The first thing we need is a base class we are actually going to derive from. This is because IronPython doesn’t compile its code into a static type but VB requires its variables to be typed. This is the base class I am using:

Public Class HelloWorldVB
    Public Overridable Function HelloWorld(ByVal name As String) As String
        Return String.Format("Hello '{0}' from Visual Basic", name)
    End Function
End Class

And a main module to start thing off:

Sub Main()

    Dim helloWorld As New HelloWorldVB()
    Console.WriteLine(helloWorld.HelloWorld("Maurice"))

    Console.ReadLine()
End Sub

No big surprise here [:)].


 


So how do we derive an IronPython class from our VB type?


The following code is the IronPython code I added to the file HelloWorld.py.

import clr
clr.AddReference('IronPythonTest2')
from IronPythonTest2 import HelloWorldVB

class HelloWorldIronPython(HelloWorldVB):
    def HelloWorld(self, name):
        return "Hello '" + name + "' from IronPython"

Basically this code adds a reference to the IronPythonTest2 assembly, this is my console application containing the previous VB code. Next it imports the HelloWorldVB type from the assembly. Now it know about the type we can go ahead and derive from that type and create a new one. This exactly what the line class HelloWorldIronPython(HelloWorldVB) does, it creates a new type called HelloWorldIronPython. Next we override the HelloWorld function and return a different welcome string. A few things to note here: Python uses indentation to specify blocks, so the function being indented from the class is a part of that and the line of code with the return is indented from the def that defines the function so it is part of the function body. Another interesting thing is the self parameter. Every function in Python is passed a reference to itself as the first parameter. Sort of like the implicit Me in VB except a bit more obvious.


If you want to know more about IronPython I suggest you get the book IronPython in Action from Michael Foord.



To make sure the HelloWorld.py file is available to the console application I have set the  Copy to Output Directory to Copy always.


OK so far so good. We have an IronPython class with the code we need. Now we still need to create an object from it. This isn’t hard it just takes a bit more doing than just using the New operator.


Instantiating the IronPython object


The first step is adding the required references. We need to add the following assemblies:


  1. IronPython.dll
  2. IronPython.Modules.dll
  3. Microsoft.Scripting.dll
  4. Microsoft.Scripting.Core.dll

We will only be using the 1st and 3rd ourselves but the others are needed as well.


 


Once we have the references set we can add the required Imports:

Imports Microsoft.Scripting.Hosting
Imports IronPython.Hosting
Imports IronPython.Runtime.Types

And now we can get really going with the code [:)]


We need to load the file with the Python source code using an IronPython ScriptRuntime. Once done we can get a reference to the IronPython type object using the GetVariable() function by passing in the class name. Once we have that we call the ScriptRuntime again to actually create the object. See the code below:

Dim runtime As ScriptRuntime = PythonEngine.CurrentEngine.Runtime
Dim scope As ScriptScope = runtime.ExecuteFile("HelloWorld.py")
Dim pythonType As PythonType = scope.GetVariable(Of PythonType)("HelloWorldIronPython")
helloWorld = CType(runtime.Operations.Call(pythonType), HelloWorldVB)
Console.WriteLine(helloWorld.HelloWorld("Maurice"))

 


And with this code we are good to go. Running the complete code will show the output below:


image


The complete code in the main module:

Option Explicit On
Option Strict On

Imports Microsoft.Scripting.Hosting
Imports IronPython.Hosting
Imports IronPython.Runtime.Types

Module Module1
    Sub Main()
        Dim helloWorld As New HelloWorldVB()
        Console.WriteLine(helloWorld.HelloWorld("Maurice"))

        Dim runtime As ScriptRuntime = PythonEngine.CurrentEngine.Runtime
        Dim scope As ScriptScope = runtime.ExecuteFile("HelloWorld.py")
        Dim pythonType As PythonType = scope.GetVariable(Of PythonType)("HelloWorldIronPython")
        helloWorld = CType(runtime.Operations.Call(pythonType), HelloWorldVB)
        Console.WriteLine(helloWorld.HelloWorld("Maurice"))

        Console.ReadLine()
    End Sub
End Module

 


Enjoy!

One thought on “Calling IronPython functions from .NET

  1. How to create an Python object without having a
    VB class from which the Python class was derived?

    If you have a Python modul in source and you want to create
    a class from it. How can you do that?

    Best Regards

    Gerhard

Leave a Reply

Your email address will not be published. Required fields are marked *


*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>