Introduction to .NET/SML#

Using OLE/SML#, you can access .NET objects from SML# world.

Let's write a SML# code to access a .NET object implemented in the following C# code( HelloDotNETWorld.cs ).

using System.Runtime.InteropServices;

public interface IHelloDotNETWorld
   string greeting(string yourName);

public class HelloDotNETWorld : IHelloDotNETWorld
   public HelloDotNETWorld(){
       System.Console.WriteLine("I am a .NET object.");

   public string greeting(string yourName)
       return "Hello, " + yourName + " !";

Compile this code by C# compiler to generate an assembly ( HelloDotNETWorld.dll ).

$ csc.exe /t:library HelloDotNETWorld.cs

Register the assembly.

$ RegAsm.exe /codebase HelloDotNETWorld.dll

Then, generate a type-library ( HelloDotNETWorld.tlb ).

$ TlbExp.exe HelloDotNETWorld.dll

From this type-library, generate a wrapper SML code ( HelloDotNETWorld.sml ).

$ OLE2SML.exe HelloDotNETWorld.tlb

Finally, SML# code can access this .NET object as follows.

use "OLE.sml";

use "./HelloDotNETWorld.sml";


val object = HelloDotNETWorld.newHelloDotNETWorld ();
val message = OLE.A (#greeting object (OLE.L "world"));
val _ = print message;

You can see a message from .NET world.

$ /usr/local/bin/smlsharp
SML# 0.40 (2010-04-30 22:11:29 --)
# use "./UseHelloDotNETWorld.sml";
structure HelloDotNETWorld : HelloDotNETWorld
val it = () : unit
I am a .NET object.
val object =
      AddRef = fn,
      GetTypeInfo = fn,
      GetTypeInfoCount = fn,
      Release = fn,
      addRef = fn,
      greeting = fn,
      release = fn,
      this = fn
    : HelloDotNETWorld.HelloDotNETWorld
val message = "Hello, world !" : String.string
Hello, world !

In another way,

$ /usr/local/bin/smlsharp ./UseHelloDotNETWorld.sml
I am a .NET object.
Hello, world !

Development of .NET/SML# just have started. Interoperability is limited yet. As we will extend OLE/SML# interface, higher level of interoperability with .NET will be possible.

About deployment.

The above example registers the assembly as follows:

$ RegAsm.exe /codebase HelloDotNETWorld.dll

Although this is an easy procedure to access .NET object on the SML# interactive session, it is not a preferred way. You will see a warning from RegAsm.exe.

RegAsm warning: Registering an unsigned assembly with /codebase can
cause your assembly to interfere with other applications that may be
installed on the same computer. The /codebase switch is intended to
be used only with signed assemblies.Please give your assembly a strong
name and re-register it. says that an assembly should be located at

  • GAC(global assembly cache)(It points to C:\Windows\assembly)
  • the application's directory, in a subdirectory of the application's directory
  • directories specified in a configuration file

Among these, the easiest is to locate the assembly at the application's directory. In our case, however, the application is SML# runtime smlsharprun.exe, and it is inconvenient to install the assembly to the SML# install directory.

If we can generate an executable file from the SML source code, the application can be located at the same directory with the assembly.


$ -o UseHelloDotNETWorld.exe ./UseHelloDotNETWorld.sml

The application ( UseHelloDotNETWorld.exe ) and the assembly ( HelloDotNETWorld.dll ) are located at the same directory now.

$ ls
HelloDotNETWorld.cs   HelloDotNETWorld.tlb     UseHelloDotNETWorld.sml
HelloDotNETWorld.dll  Makefile
HelloDotNETWorld.sml  UseHelloDotNETWorld.exe

This application can load the assembly and access a .NET object.

$ ./UseHelloDotNETWorld.exe
I am a .NET object.
Hello, world !
Last modified:2010/06/11 15:10:02
References:[Introduction to .NET/SML#] [mapping .NET/SML#] [Tools]