Embedding IronPython

IronPython & .NET Applications

Visual Studio Express

 

 

Note

This is part of a series of articles on embedding IronPython:

For a much more in depth introduction to hosting and interacting with dynamic languages from .NET applications see chapters 14 & 15 of IronPython in Action.

Introduction

Caution!

This article uses the IronPython 1 hosting API. It will be updated for IronPython 2 shortly...

One of the great things about IronPython is that it is a ready made scripting engine for dotnet applications. Embedding the IronPython engine into an existing application is a great way to expose an API for user scripting; and IronPython makes it almost ridiculously easy. Smile

This isn't the only reason why you might want to embed the IronPython engine into a C# application. Creating a custom executable, perhaps with custom behaviour before executing Python code is another [1]. Creating a custom executable is also the simplest example of embedding IronPython; so this is what this short article illustrates.

Getting Started

This example is taken from the Tabbed Images program written by myself, Andrzej Krzywda and Christian Muirhead [2]. It can be compiled with Visual Studio Express, the free Microsoft C# compiler.

You could also use csc.exe (comes with the .NET framework) to compile it. You could automate this as part of your build process with MSBuild or nant.

You will need the DLLs IronMath.dll and IronPython.dll from the IronPython project.

We compiled this code as a Windows application for Tabbed Images (no console box) and associated an icon with the executable.

The C# Code

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Windows.Forms;
using IronPython.Hosting;
using IronPython.Runtime;

namespace TabbedImages {

    class TabbedImages {

        [STAThread]
        static void Main(string[] rawArgs) {
            List<string> args = new List<string>(rawArgs);
            args.Insert(0, Application.ExecutablePath);

            PythonEngine engine = new PythonEngine();
            engine.AddToPath(Path.GetDirectoryName(
                Application.ExecutablePath));
            engine.Sys.argv = List.Make(args);

            EngineModule engineModule = engine.CreateModule(
                "__main__",  new Dictionary<string, object>(), true);
            engine.DefaultModule = engineModule;

            string path = Path.Combine(
                Path.GetDirectoryName(Application.ExecutablePath),
                                      "main.py");
            engine.ExecuteFile(path);

        }
    }
}

What it Does

It's a pretty simple example, so if you speak C# it probably doesn't need much explanation. Smile

It uses the IronPython.Hosting and IronPython.Runtime namespaces, so the project will need references to the IronPython DLLs.

Like every C# application we have to have a class. The only method is the static method Main, which is the entry point for the application (automatically executed when the program is run).

The code creates an instance of the IronPython engine :

PythonEngine engine = new PythonEngine();

We ensure that the application directory is on the path, so that imports will work as usual :

engine.AddToPath(Path.GetDirectoryName(Application.ExecutablePath));

We want our application to behave the same way when run from our executable as when it is run from ipy.exe (the default IronPython interpreter). We need to configure sys.argv to contain the application executable followed by any command line arguments. This is done with :

engine.Sys.argv = List.Make(args);

args is a generic list that has already been prepared. List.Make is a call to the IronPython type List.

We'd like our application to run in the __main__ module, which is standard behaviour in Python for the main script. We set this up by creating an IronPython module, giving it a name, and setting it as the default module on the engine :

EngineModule engineModule = engine.CreateModule("__main__",
    new Dictionary<string, object>(), true);
engine.DefaultModule = engineModule;

If you were exposing a scripting API to your application, you could prepopulate a module with objects for the user to work with.

Finally we execute our Python script by calling a public method on the engine :

engine.ExecuteFile(path);

Again, if you were exposing a scripting API you might not want to use ExecuteFile method. The IronPython API documentation has good documentation for both the PythonEngine and EngineModule. Configuring and using these to expose a program API are subjects that will be covered in IronPython in Action of course. Smile

Note

There are some more examples of playing with the PythonEngine in Embedding IronPython... in IronPython.

This uses and configure new IronPython engines from IronPython!

[1]Startup speed is not one of IronPython's great virtues. You may want to do things like 'single instance' checking from C# before entering IronPython code.
[2]As an example of developing with IronPython and Windows Forms.

For buying techie books, science fiction, computer hardware or the latest gadgets: visit The Voidspace Amazon Store.

Hosted by Webfaction

Return to Top

Page rendered with rest2web the Site Builder

Last edited Fri Nov 27 18:32:35 2009.

Counter...