A 3 minute guide to embedding IronPython in a C# application
Despite knowing absolutely nothing about Python, I've had a lot of fun and a few lttle victories with it tonight. I've built two small apps that I'll include the code for below.
I've avoided IronPython up until now, but a terrible problem has arisen lately.
I've decided to write my own text editor.
This is a bad thing. Only fools write their own text editor. Soon, hair will start growing on the palms of my hands.
But, since I'm looking for some extensibility in this editor idea (of which I'll show more in a subsequent post) I realised that hosting IronPython is the best way to get the sort of scripting I'm after.
Hosting IronPython in C# is well-trodden turf. Many other have been there and blogged it before. But the fun was really in the doing.
Here's two very short demo apps I wrote tonight, literally in under an hour.
First, by following the example Bernie Almosni provides in Extending your c# application with IronPython I built a little interactive calculator, with a history.
The code is trivial and can be downloaded below.
The next example is also trivial, but I'll step through the code just quickly, since it's a superset of the previous example.
I wrote a little application that lets you write python code to alter the contents of a textbox. This is the heart of the editor I have in mind -- and it's barely 10 lines!
So, in a fresh C# winforms app, I added references to all the dll's in
C:\Program Files\IronPython 2.0.1 (I didn't know which dlls i needed exactly -- so i referenced them all ;-) )
I created a new form and dropped two text boxes and a button on it, as you'll see in the screenshot.
I added these using statements:
I created two module levels variables, one to hold the IronPython engine, and one to tell it the 'scope' of the variables I want to share with it.
private ScriptEngine m_engine = Python.CreateEngine();
private ScriptScope m_scope = null;
Upon form_load, I construct the scope, and add the target text box to it. (This is the text box our Python code will be able to act upon.)
m_scope = m_engine.CreateScope();
When the user clicks the button, I compile the code in the first box, and execute it as a statement.
Dead simple. Ridiculously simple.
string code = CommandTextBox.Text.Trim();
ScriptSource source = m_engine.CreateScriptSourceFromString(code, SourceCodeKind.SingleStatement);
With that in place, the python code entered at runtime, such as:
txt.SelectedText = txt.SelectedText.upper()
...has the desired effect of making the selected text uppercase.
I got the same effect in C# once, but it took five assemblies, hundreds of lines of code... it was terribly fragile and I broke it beyond repair before I got it to a source repository. A tragic episode, i still feel like stabbing someone every time I think about it. (LFT much?)/p>
So -- here's the source code:
And here's a couple of other articles on the same topic:
- Embedding the Dynamic Language Runtime: Articles, Tutorials and Examples
- Make your .NET application extendible using DLR : IronPython