Hosting IronPython 2.0 Alpha 6 via the DLR

We previously discussed the hosting model of IronPython 1.1.  This time around we'll see how that model was updated in the latest Alpha release by reviewing an updated version of the same example.

It should be noted that the model presented here is changing very soon.  So why discuss it?  Well, two reasons.  The first is practical in that this is the model you'll deal with when using the latest binaries.  But also, I think some of you might find the insight into our model's evolution interesting.

Here's our updated example:

using System;
using Microsoft.Scripting; //From Microsoft.Scripting.dll
using Microsoft.Scripting.Hosting; //From Microsoft.Scripting.dll
//You'll also need to reference IronPython.dll
//and IronPython.Modules.dll

namespace Hosting2 {
    class Host {
        public static void Main() {
            //Get the IronPython ScriptEngine for the current domain
            //and create a ScriptModule to execute in.
            ScriptDomainManager sdm = ScriptDomainManager.CurrentManager;
            LanguageProvider pyprov = sdm.GetLanguageProvider("python");
            ScriptEngine pe = pyprov.GetEngine();
            ScriptModule mod = sdm.CreateModule("mymod");


            //Expose host data to IronPython and vice versa
            mod.SetVariable("mystring", "This is a C# string");
            pe.Execute("print mystring", mod);

            pe.Execute("mystring = 'This is a Python string'", mod);
            Console.WriteLine(mod.LookupVariable("mystring"));


            //Expose a host method to IronPython and vice versa
            HostAPI myapi = new HostAPI();
            mod.SetVariable("api", myapi);
            pe.Execute("api.Method()", mod);

            pe.Execute(@"def func():
    print 'This is a Python function'
", mod);
            pe.Evaluate("func()", mod);


            //Use delegates over the same two methods
            HostAPI.Del hostdel = new HostAPI.Del(myapi.Method);
            mod.SetVariable("hdel", hostdel);
            pe.Execute("hdel()", mod);

            HostAPI.Del ipydel = pe.EvaluateAs<HostAPI.Del>("func",
                mod);
            ipydel();
        }
    }

    public class HostAPI {
        public delegate void Del();

        public void Method() {
            Console.WriteLine("This is a host method");
        }
    }
}

What's changed and why?

We've switched from using IronPython.Hosting to using Microsoft.Scripting.Hosting.  Microsoft.Scripting is the primary namespace of the DLR, which 2.0 builds of IronPython are based on.

The DLR's hosting model is designed to support many different dynamic languages.  So instead of simply constructing a PythonEngine as we did in 1.1, we ask the DLR to provide us with the ScriptEngine mapped to the language "python" in this AppDomain.

            ScriptDomainManager sdm = ScriptDomainManager.CurrentManager;
            LanguageProvider pyprov = sdm.GetLanguageProvider("python");
            ScriptEngine pe = pyprov.GetEngine();

In the process we've introduced two entirely new types: ScriptDomainManager and LanguageProvider.  Every AppDomain in a DLR host has exactly one ScriptDomainManager.  Among other things, ScriptDomainManager tracks which languages are available on the system.  In this case we've asked the ScriptDomainManager to give us the LanguageProvider mapping to Python.  If we had an appropriate version of IronRuby installed, we could ask for Ruby in exactly the same manner.  We use the LanguageProvider to give us language-specific services including the ScriptEngine.

For an execution scope, we're using a ScriptModule instead of the EngineModule type we used in 1.1.  Accessing the contents of a ScriptModule is a little different but shouldn't be too jarring.

Lastly, in 1.1 we were able to create a delegate to IronPython code by calling PythonEngine.CreateMethod with a string of code to wrap in a delegate.  That method no longer exists in 2.0.  But we can still get a delegate to an IronPython function by evaluating a function as our target delegate.

            HostAPI.Del ipydel = pe.EvaluateAs<HostAPI.Del>("func",
                mod);
            ipydel();

And actually, this same code snippet works in 1.1 as well.


But you could have done...

Some of you may note that there are several ways I could've written this example for 2.0 Alpha 6, and many of them are simpler than the one I chose.  For instance, this one line of code:

            ScriptEngine pe = IronPython.Hosting.PythonEngine.CurrentEngine;

Is equivalent to these three lines:

            ScriptDomainManager sdm = ScriptDomainManager.CurrentManager;
            LanguageProvider pyprov = sdm.GetLanguageProvider("python");
            ScriptEngine pe = pyprov.GetEngine();

I chose the latter to provide a more language independent view of the API, which is a central driving force behind our redesigns.

Furthermore, for this very simple example we could've used the Microsoft.Scripting.Script class.  Consider the following complete program:

using Microsoft.Scripting;

namespace Hosting2 {
    class Host {
        public static void Main() {
            Script.SetVariable("mystring", "This is a C# string");
            Script.Execute("python", "print mystring");
        }
    }
}

The Script class is intended as an entry level hosting introduction and doesn't allow things like executing in a non-default ScriptModule.


Next...

In this post we've looked at the hosting model of 2.0 Alpha 6 and some ways it differs from the model of 1.1.  Next time we'll look at the (hopefully) final hosting model for the DLR and talk more about the design evolution.

Published 29 November 07 09:59 by rdawson
Filed under: , ,

Comments

# asp to go said on March 28, 2008 1:35 PM:

Interesting take on Script class and its relation to the entry level hosting environment.  If anyone is in need of a great web host, our developers have been very happy with Server Intellect, who was one of the first Windows Web Hosts that is Microsoft Gold Certified to offer Windows Server 2008 'Longhorn' on all of its Dedicated Servers.

# Rob Relyea - Xamlified said on March 29, 2008 8:23 PM:

DLR is the Dynamic Language Runtime...a library for the CLR (.Net or Silverlight) that enables &quot;scripting&quot;

Anonymous comments are disabled

About rdawson

Born and raised in Kansas City, Missouri. Graduated from the University of Missouri at Rolla. Moved to Redmond, Washington in 1999 where I've been working as a Software Development Engineer in Test for Microsoft ever since. In my spare time I enjoy riding my motorcycle and am learning to play the violin and speak French.

Search

This Blog

Syndication

Page view tracker