I en tidligere post så vi hvor nemt det var at komme igang med IronPython og jeg håber det kom frem at det virkligt er mærkbart nemmere end at skulle til at bruge C#/VB.Net som scriptsprog. Hvis ikke så prøv at forklar dig selv hvordan et enkelt delegate kald (som f.eks. add(2, 3)) skal wrappes for at køre som C# script. Eller hvor meget reflection du skal bruge for at få adgang til en delegate eller kallse du har definere i dit script.

Nu vil jeg forsøge at beskrive det sidste i IronPython, altså hvordan man kan bruge Python klasser i C#. Vi begynder med at definere en simpel Python klasse.

class MyClass(object):
    def add(self, a, b): return a + b

Når koden er kørt vil vores scope indeholde en variabel med navnet på klassen, her MyClass.

object myClass = scope.GetVariable("MyClass"); 

Dette er klassedefinition som vi skal bruge til at oprette en ny instans of klassen og til at kalde methoder på klassen. Vi skal også bruge ObjectOperations fra vores engine.

ObjectOperations op = engine.Operations; 

Herefter er det bare at gå igang med at oprette en instans, finde methoden og kalden metoden:

object instance = op.Call(myClass);
object method = op.GetMember(instance, "add");
int sum = (int)op.Call(method, 2, 3);

Hvis sum ikke er 5, så gik det galt (and you're on your own). Det var det. Måske nogle kan genkende et mønster fra IDispatch.Invoke, eller der det bare mig der fik et deja-vu. Med dynamic i C# 4.0 skulle det blive meget nemmere med disse operationer, fordi det er speciel designet til at kode op mod f.eks. Office objekt modellen, men det ser vi på til den tid.

Jeg var egentlig i gang med at skrive et indlæg om hvor let det var at integrere IronPython i egne programmer, da jeg stødte på A 3 minute guide to embedding IronPython in a C# application. Så indlægget blev sat på stand-by, men det er et sjovt emnu og nu kommer det så alligevel - men vi prøver at gøre det på kun 2 minutter.

Lige en hurtig disclaimer inden kommer for godt i gang: Jeg er ny til Python som sprog og platform. Det med de to minutter er måske også en underdrivelse, men den tid det ta'r at komme i gang med IronPython er stærkt korreleret med hastigheden for på din internetforbindelse.

Det først der skal ske er at du downloader IronPython fra http://www.codeplex.com/IronPython. Minimum requirement for IronPython 2.0 er .NET 2.0 SP1. Det vil kræve den største del af de to minutter. Du kan bruge Python konsollen (ipy.exe) til at eksperimentere med Python og så er du sådan set i gang. Den medfølgende tutorial kan anbefales hvis du vide mere om integrationen mellem .NET og Python.

Det sjove kommer når man begnder at integrere IronPython med egne programmer. IronPython er baseret på Dynamic Language Runtime (DLR) og bortset fra det rent Python specifikke, så vil andre DLR sprog kunne integreres på samme måde. Så selvom Python konsollen er smart vil du nok begynde at kede dig efter to minutter.

Det eneste du skal bruge er en ScriptEngine og et ScriptScope.

ScriptEngine engine = Python.CreateEngine();
ScriptScope scope = engine.CreateScope();

Tada. Du skal naturligvis referere IronPython.dll, Microsoft.Scripting og Microsoft.Scripting.Core. ScriptEngine er det springende punkt for valgt af sprog. Andre sprog, som f.eks. IronRuby, sættes op på lignende måde, men med en anden engine.

Så er det bare at fyre noget kode afsted. Lad os starte med et simpelt udtryk:

string input = "3+3";
ScriptSource source = engine.CreateScriptSourceFromString(input, SourceCodeKind.Expression);
source.Execute(scope);

Det er i sig selv ikke så imponerende, de fleste af os kunne regne det ud i hovedet. Men hvis vi skal køre egentlig Python kode skal SourceCodeKind blot ændres til f.eks. Statements eller File.

Vi er endnu ikke kommet meget længere end vi var med ipy.exe, så lad mig lige bruge det sidste af de 2 minutter på at vise hvor nemt det er at integrere dine C# klasser. For at gøre variable tilfængelige i IronPython skal de blot tilføjes til dit scope.

scope.SetVariable("xyz", new Xyz());
scope.SetVariable("add", new Func<double, double, double>(delegate(double a, double b) { return a + b; }));

Den sidste variable bliver en funktion og svarer til det klassiske begynder-eksempel:

def add(a, b):
    return a + b;

Xyz klassen fungerer nu som enhver anden klasse, som beskrevet i Tutorial. Prøv evt med dir(xyz).

Håber det giver dig inspiration til at prøve hvordan du kan integrere IronPython med dine egne programmer.