Using Python Classes from .NET

From IronPython Cookbook

Python classes are much more mutable than C# classes, you can add members at runtime and swap out the class of instances or the base classes on the class itself.

This means that you can't treat Python classes as C# classes, but it is still possible use them from C#. We can pull the class out of a Python engine (as 'UserType'). We can then use 'Ops.Call' to create a new instance. In order to use the new class, the compiler needs to know which methods (etc) are available on it.

The best way of doing this is for our Python class to inherit from a .NET class (or implement an interface) and then we can cast the object that comes out of 'Ops.Call' to this type.

This example uses the IronPython 1.X API.

using System;
using IronPython.Hosting;
using IronPython.Runtime.Types;
using IronPython.Runtime.Operations;

namespace TestPythonConsole
{
    class Program
    {
        static void Main()
        {
            string code = "import clr\r\nclr.AddReference('TestPythonConsole')\r\nfrom TestPythonConsole import Test\r\nclass X(Test):\r\n     def test(self):\r\n        return 'hello'\r\n\r\n";
            PythonEngine engine = new PythonEngine();
            EngineModule module = engine.CreateModule();
            engine.DefaultModule = module;
            engine.Execute(code);
            UserType ptype = module.Globals["X"] as UserType;
            Test obj = Ops.Call(ptype) as Test;
            Console.WriteLine(obj.test());
        }
    }

    public class Test
    {
        virtual public string test() 
        { 
            return "goodbye";
        }
    }

}

The Python code imports 'Test' (it has to add the right reference to the assembly first). It then subclasses 'Test' in a class called X.

The class we pull out of the Python engine globals is called and the result cast to Test.

Calling the method 'test' calls the subclass rather than the parent class. You can tell this works if it prints 'hello' rather than 'goodbye' when you run it.

Just to make it clearer, the Python code is:

import clr
clr.AddReference('TestPythonConsole')
from TestPythonConsole import Test

class X(Test):
     def test(self):
        return 'hello'

If you want to execute Python code from a file rather than from an embedded string, you can replace the call to 'engine.Execute(code);' with a call to the 'ExecuteFile' method instead:

engine.ExecuteFile("test.py");


Back to Contents.

TOOLBOX
LANGUAGES