[IronPython] IP 2.0 Alpha 7 embedding

Slide slide.o.mix at gmail.com
Fri Dec 21 22:39:59 CET 2007


I have come up with an example (very simple) of embedding IP 2.0 into
a C# app and doing back and forth handling of objects (objects
declared in Python and object declared in C#). I am interested to know
if I am doing some things the best way as I've just been going kind of
hit and miss. Can someone do a little critiquing of this code and see
if I am being dumb? The windows app has two RichTextBoxes on it (one
for input, the other for output), a clear button and a "go" button.
When the "go" button is pressed, it writes the source out to a temp
file and then creates the object instance from the script. Thanks!


Here is the code:


test.py
============================================
import TestLib, unittest

def Print(message):
	output.AppendText("%s\r\n" % message)

class Test(TestLib.ITest):
	def Print(self, message):
		output.AppendText("%s\r\n" % message)

Print("Hello, world!")




ITestLib.cs located in TestLib.dll
==========================================
using System;
using System.Collections.Generic;
using System.Text;

namespace TestLib
{
    public interface ITest
    {
        void Print(string message);
    }
}



MainForm.cs located in IPEmbed.exe which references TestLib.dll
============================================
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.IO;
using System.Windows.Forms;

using Microsoft.Scripting;
using Microsoft.Scripting.Hosting;

using IronPython.Runtime;
using IronPython.Hosting;

namespace IPEmbed
{
    public partial class Form1 : Form
    {
        private ScriptScope __main__;
        private LanguageContext _context;

        public Form1()
        {
            InitializeComponent();

            _context = LanguageContext.FromEngine(PythonEngine.CurrentEngine);
            _context.SetScriptSourceSearchPaths(new string[] {
Environment.CurrentDirectory,
Path.Combine(Environment.CurrentDirectory, "Lib") });
        }

        // sets up the script engine, etc
        private void go_Click(object sender, EventArgs e)
        {
            ScriptDomainManager.CurrentManager.Host.DefaultModule.ClearVariables();

            if (input.Text.Length == 0)
                return;

            string filepath = Path.GetTempFileName();
            File.WriteAllText(filepath, input.Text);

            __main__ =
ScriptDomainManager.CurrentManager.CompileModule("__main__",
SourceUnit.CreateFileUnit(_context, filepath));
            ScriptDomainManager.CurrentManager.PublishModule(__main__,
"__main__");

            Microsoft.Scripting.ClrModule.GetInstance().AddReference("TestLib");
            __main__.SetVariable("output", output);
            __main__.Execute();

            TestLib.ITest test = CreateInstanceFromInterface<TestLib.ITest>();
            if (test != null)
                test.Print("Hello, world!");
        }

        // this method will find a class in the python code that
implements a given interface and create and instance
        // of that class, returning it as the interface
        private T CreateInstanceFromInterface<T>()
        {
            T result = default(T);

            IAttributesCollection attrs =
IronPython.Runtime.Types.PythonModuleOps.Get__dict__(__main__);
            foreach (KeyValuePair<object, object> attr in attrs)
            {
                IronPython.Runtime.Types.PythonType attr_type =
attr.Value as IronPython.Runtime.Types.PythonType;

                if (attr_type != null)
                {
                    foreach (IronPython.Runtime.Types.PythonType dt in
attr_type.BaseTypes)
                    {
                        if (dt.UnderlyingSystemType != null &&
dt.UnderlyingSystemType == typeof(T))
                        {
                            CodeContext context = new
CodeContext(__main__.Scope, _context, new ModuleContext(__main__));
                            result = (T)attr_type.CreateInstance(context);
                            break;
                        }
                    }
                }
            }
            return result;
        }

        private void clear_Click(object sender, EventArgs e)
        {
            output.Clear();
        }
    }
}



More information about the Ironpython-users mailing list