Using Scala in .NET
By Adrian Sutton
Having become quite interested in languages that support deployment on both Java and .NET, then diving into Scala to find it’s a good language, the obvious next step is to try using Scala on .NET. I found a little time over the weekend to try that out with good success. Notably, I haven’t tried this in a real project yet so there may yet be some significant catches, but so far it looks really quite promising.
Simple .NET Exe
First things first, let’s write some Scala then compile it to a .exe file that uses .NET. Our scala class is the simple Hello World:
import System.Console object test extends Application { def main(args: Array[String]) = Console.println(“Hello .NET World!”) }
Note that I put this in a file called test.scala as part of my fiddling to make this work – I don’t think that should be required but it certainly doesn’t hurt.
Compilation to .NET requires two steps. Both are best performed by opening the “SDK Command Prompt”1{#footlink1:1255960347063.footnote}. This looks very much like the normal Command Prompt but it defines a bunch of important environment variables so that all the .NET tools are on your path and working correctly.
-
If you haven’t already, as the Scala docs say, copy the mscorlib.dll file from the .NET SDK (I had to use find to locate it then picked one of the results at random) to the %SCALA_HOME%\share\scala\lib directory
-
Again, if you haven’t already, install the scala-msil support by running:
sbaz install scala-msil
-
Then compile to the MSIL intermediary format with scalac-net2{#footlink2:1255960467317.footnote}:
scalac-net test.scala
Now you should have a test.msil file alongside the test.scala file. The next step is to convert the file to an actual EXE file with the ilasm tool3{#footlink3:1255960786099.footnote}:
ilasm test.msil
Now you should have test.exe alongside your test.msil and test.scala files. Before you run it though, you’ll need to find the predef.dll and scalaruntime.dll files in the Scala distribution and copy them to the current directory4{#footlink4:1255960886737.footnote}.
Finally, you can now run test.exe and see “Hello .NET World!” printed.
Creating DLLs for Visual Studio Projects
The same tool setup can be used to create DLLs for use with Visual Studio projects. I created a C# web application project in Visual Studio, then modified my test scala class slightly:
import System.Console class test extends Application { def getStuff) = “Hello .NET World!” }
Then recompile it with scalac-net as before. Since we want a DLL instead of an EXE file we add a /dll parameter to the ilasm invocation:
ilasm /dll test.msil
Now we’ve got a DLL ready to go. I copied the three DLLs, test.dll, predef.dll and scalaruntime.dll into my Visual Studio project to make them easy to access. Then:
- Right click on the project in Visual Studio
- Select “Add Reference…”
- Click the “Browse” tab
- Select the three DLLs you copied in.
- Click “OK”
You can now access your Scala class from C# quite easily. I edited Default.aspx and added:
<%= new test().getStuff() %>
Code completion even worked. Running the project correctly shows “Hello .NET World!”.
Stuff Yet To Discover
There’s a lot of stuff I don’t know about yet, largely because I’m starting from pretty much no knowledge of .NET programming, but also a few Scala related things:
- Unlike Ruby and Python, Scala doesn’t have a class library that’s designed to stand alone – it somewhat assumes the Java libraries will be there. Things like IO are left to the Java classes so they’d need to be abstracted away with separate Java and .NET implementations. It remains to be seen how limiting that could be.
- Worse, I’ve seen some blog posts mention that not all of the Scala library is actually available on .NET. The XML libraries directly reference a bunch of Java IO stuff for example.
- You can combine multiple classes in one DLL. When I still had test as an object, I got ‘test’ and ‘test$’ put into the DLL. When I have multiple .scala files to compile I’m not sure at what point or how they all get combined into one DLL. I’m guessing somewhere along the line putting all the files as arguments should do the trick. Otherwise it will get pretty unwieldy.
- I’ve got no idea what actual deployment of this stuff is like. Last time I touched .NET that was a complete nightmare even without Scala. Hopefully if the project references all the Scala DLL files they will get bundled up in whatever way Visual Studio would normally do when preparing to distribute.
1 – I believe this was installed along with the .NET SDK 2.0 package I grabbed – I didn’t notice it being installed with just Visual Studio but I could be wrong. ↩
2 – scalac-net seems to be a handy little wrapper around scalac that sets -target=msil and adds the right DLLs to the classpath. ↩
3 – this is the part that really requires the SDK Command Prompt and the environment variables it sets up.↩
4 – I think under Windows DLL loading rules they can actually be anywhere on the PATH. ↩