SML# - DotNETSMLSharpIntroduction Diff

  • Added parts are displayed like this.
  • Deleted parts are displayed like this.

//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
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 !

!Topics in .NET/SML#.