We can call into Silverlight from Javascript using one technique, and a slightly different one for calling from Silverlight into Javascript. Both of them are based on marking classes and methods with .NET attributes. These are useful techniques for creating hybrid applications that are partly written in Silverlight and partially written in Javascript. As Python code running in Silverlight runs faster than Javascript (and Python is a nicer language of course), you could even use Silverlight as an optional accelerator for RIAs (Rich Internet Applications) - falling back to Javascript when Silverlight is unavailable.

Unfortunately we can't set attributes from IronPython, so we have to use a bit of C#. Fortunately we can create a stub-class, and then subclass from IronPython. The C# is simple enough that, even if you have never seen C# before, you should be able to understand it.

Note

As well as the techniques shown in this article, you can add Python event handlers to Javascript, and call Javascript functions, all from within Silverlight and without having to use C#. These techniques can still be useful however.

The Scriptable attributes lives in the System.Windows.Browser namespace. C# can be compiled using Visual Studio 2008 (or MonoDevelop). From Visual Studio you will also need Visual Studio tools for Silverlight installed. Fortunately you don't need these installed to compile assemblies for Silverlight - we'll see how in a few moments.

This uses the ScriptableTypeAttribute and ScriptableMemberAttribute attributes

We need a class marked as Scriptable with a method marked as Scriptable. The method should call a virtual method that we can override in an IronPython subclass. The Python subclass will still be marked as Scriptable, as will its Scriptable method. If we want to pass and return arguments they need to be statically typed, and can only be a primitive like a string or an integer. This isn't really a problem though because we can pass or return JSON as a string. There is a JSON serializer and deserializer available with Silverlight, and using JSON from Javascript is easy of course!

To use this from IronPython we need to import the class from the assembly we have compiled, adding a reference to it in the normal way (and making sure that it is included in the manifest / xap of course):

If you are using clr.AddReference to access the assembly then the assembly must be in the application manifest file (AppManifest.xaml). Another alternative is to just include the assembly in the xap but not add it to manifest, and use clr.AddReferenceToFile to add the reference.

Once we have registered the scriptable object, it is then available on the control to be called from Javascript. This is made easier by giving the Silverlight control an id in the object tag in the html.

You can only do your hooking up after the Silverlight control has loaded. The easiest way to do this is inside a Javascript function that you specify in the onload parameter of the Silverlight control element:

We need to register this on both the IronPython and the Javascript side. The Javascript needs to attach an event handler to the event we have exposed. When we fire the event from inside Silverlight, the handler will receive the eventargs we pass in from the IronPython side and be able to access the scriptable members we gave it. The Javascript side can modify those members to return values.

When event.OnEvent(args) is called from Python, the javascript function (some_function) is called and receives the arguments sender and our event args. The Javascript can modify the attributes on the event to return values. After the call returns, IronPython can look at the attributes on the event args to retrieve any return values.

Just like with calling from Javascript into Silverlight, we can only hook up the event to its Javascript function once the Silverlight control has loaded and you have registered the event. Again, the usual way to do this is in an onload function with the same caveat as previously.

Having to download Visual Studio 2008 (and that is one hefty download) just to compile a few lines of C# is a nuisance. Fortunately we can get round this by using the .NET 2 compiler to do it for us. (I think that the compiler, csc.exe, comes with the .NET 2 SDK - but it may even be included in a normal .NET 2 install.)

The following batch file tells csc to compile with references to the Sivlerlight DLLs instead of the standard framework ones. It compiles all the C# files in the directory (*.cs) into an assembly specified by the /out argument (/out:SilverlightApp.dll).

The lines that start %csc% need to be all on one line - I've split it into multiple lines here for readability. The paths I've included above are the paths that I found csc and the Silverlight assemblies on my machine (Windows Vista). You may need to modify them for yours. I haven't tried this with Mono on the Mac, but I would be interested to hear from anyone who gets it working (or otherwise).

From compiling C# for use with IronPython, the next logical step is embedding the IronPython interpreter in a C# Silverlight application: