I’ve heard plenty of times on the IronPython Mailing List that embedding IronPython in Silverlight is easy at first, but then you fall off a cliff when trying to import, be it from a .NET namespace, the Python built-ins, or even other Python files. Let me clear some things up, and fix some code in the process.
Slight detour – Embedding in Silverlight 101
First off, Michael Foord has an article on his website about Embedding IronPython in Silverlight, which still works. However, that’s a ton of complicated code, all having to do with creating a ScriptRuntime
instance correctly configured for Silverlight. To make this much less verbose, DynamicEngine.CreateRuntime
(in the Microsoft.Scripting.Silverlight
namespace) will create a ScriptRuntime
all prepped for use in Silverlight; this significantly reduces the boilerplate hosting code:
In case you need to customize your ScriptRuntime
, the DynamicEngine.CreateRuntimeSetup
method is there to create a ScriptRuntimeSetup
object configured for Silverlight, which then you can tweak things as necessary and create your own ScriptRuntime
.
Note: The IronPython sources currently are broken for embedding, but in the next few days the sources should reflect what this post shows.
Testing that "import" works
Ok, great, the boilerplate hosting code doesn’t need to look hideous, but let’s get back on track.
Embedding IronPython in Silverlight – importing test (sources)
Here’s a quick test of IronPython’s ability to import various modules in Silverlight, testing this exact code works while being embedded:
None of these worked when I first wrote the tests, since there was an exception being thrown in the XAP-virtual-filesystem, reported yesterday on the IronPython mailing list. But with that fixed, the import bar.baz
case still failed:
[FAIL] Traceback (most recent call last): at test_import in foo.py, line 5 ImportError: No module named bar.baz
Here's the layout of the Python files in the XAP
foo.py bar/ bar/__init__.py bar/baz.py
Application.GetResourceStream("bar/__init__.py")
was returning null
, though bar/__init__.py
was definitely inside the XAP. However, bar/__init__.py
was empty, and it turns out that Application.GetResourceStream
returns null
if the file is empty as well as if it doesn’t exist! Putting a single space in bar/__init__.py
(or anything that will make the file not empty … I suggest a comment) causes it to be found, and then bar/baz.py
can be imported properly.
So, moral of the story:
“an empty file in the XAP is a non-existent file!”
Anyway, I hope that clears up some of the issues most people initially face with embedding IronPython in Silverlight. Let me know if there are any more issues.
Note: As I said before, the current IronPython sources are broken for embedding, but in the next few days the sources should reflect what this post shows. If you’re impatient, grab these binaries.