Figure 2

Figure 2 DllImport
namespace System.Runtime.InteropServices {
 public class DllImportAttribute : Attribute {
  public DllImportAttribute(String dllname);
// EntryPoint overrides method name for GetProcAddress
  public String            EntryPoint;
// ExactSpelling disables W/A _@ mangling
  public bool              ExactSpelling;
// cdecl, stdcall, etc
  public CallingConvention CallingConvention; 
// unicode/ansi/auto
  public CharSet           CharSet;           
// function calls SetLastError
  public bool              SetLastError;
// treat native result as an HRESULT a la [retval]
  public bool              TransformSig;
 }
}
Figure 3 Using DllImport
using System.Runtime.InteropServices;

public class K32Wrapper {
  [ DllImport("kernel32.dll") ]
  public extern static void Sleep(uint msec);
  [ DllImport("kernel32.dll", EntryPoint = "Sleep") ]
  public extern static void Doze(uint msec);
  [ DllImport("user32.dll") ]
  public extern static uint MessageBox(int hwnd, String m, 
                                       String c, uint flags);
  [
    DllImport("user32.dll", EntryPoint="MessageBoxW",
              ExactSpelling=true, CharSet=CharSet.Unicode)
  ]
  public extern static uint UniBox(int hwnd, String m, 
                                   String c, uint flags);
}
Figure 4 Using DllImport with TransformSig
using System.Runtime.InteropServices;

public class OLE32Wrapper {
  [ 
    DllImport("ole32.dll", 
              EntryPoint="CoImpersonateClient")
  ]
  public extern static int CoImpersonateClient1();

  [ 
    DllImport("ole32.dll", 
              EntryPoint="CoImpersonateClient", 
              TransformSig=true) 
  ]
  public extern static void CoImpersonateClient2();
}
Figure 6 Isomorphic and Nonisomorphic Types
Type Name
Type
Description
Single
Isomorphic
Marshals as native type
Double
Isomorphic
Marshals as native type
SByte
Isomorphic
Marshals as native type
Byte
Isomorphic
Marshals as native type
Int16
Isomorphic
Marshals as native type
Uint16
Isomorphic
Marshals as native type
Int32
Isomorphic
Marshals as native type
Uint32
Isomorphic
Marshals as native type
Int64
Isomorphic
Marshals as native type
Uint64
Isomorphic
Marshals as native type
Single-dimensional arrays of isomorphic types
Isomorphic
Marshals as native type
All other arrays
Nonisomorphic
Marshals as interface or safearray
Boolean
Nonisomorphic
VARIANT_BOOL or Win32 BOOL
Char
Nonisomorphic
Win32 WCHAR or CHAR
String
Nonisomorphic
Win32 LPWSTR/LPSTR or BSTR
Object
Nonisomorphic
VARIANT (COM Interop only)
Figure 8 MarshalAs with Parameters
using System.Runtime.InteropServices;

public class FooBarWrapper {

// this routine wraps a native function declared as
// void _stdcall DoIt(LPCWSTR s1, LPCSTR s2,
//                    LPTSTR  s3, BSTR s4);

  [ DllImport("foobar.dll") ]
  public static extern void DoIt(
    [MarshalAs(UnmanagedType.LPWStr)] String s1,
    [MarshalAs(UnmanagedType.LPStr)] String s2,
    [MarshalAs(UnmanagedType.LPTStr)] String s3,
    [MarshalAs(UnmanagedType.BStr)] String s4
  );
}
Figure 11 C# as a Better IDL
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

[assembly: Guid("4c5025ef-3ae4-4128-ba7b-db4fb6e0c532") ]
[assembly: AssemblyVersion("2.1") ]

namespace AcmeCorp.MathTypes {
  [ 
    Guid("ddc244a4-c8b3-4c20-8416-1e7d0398462a"),
    InterfaceType(ComInterfaceType.InterfaceIsIUnknown)
  ]
  public interface ICalculator
  {
    double CurrentValue { get; }
    void   Clear();

    void Add(double x);
    void Subtract(double x);
    void Multiply(double x);
    void Divide(double x);
  }
}
Figure 12 C# as a Better IDL (Generated TLB)
[
  uuid(4C5025EF-3AE4-4128-BA7B-DB4FB6E0C532),
  version(2.1)
]
library AcmeCorp_MathTypes
{
  importlib("stdole2.tlb");
  [
    object,
    uuid(DDC244A4-C8B3-4C20-8416-1E7D0398462A),
    oleautomation,
    custom({0F21F359-AB84-41E8-9A78-36D110E6D2F9}, 
           "AcmeCorp.MathTypes.ICalculator")    
  ]
  interface ICalculator : IUnknown {
    [propget] 
    HRESULT CurrentValue([out, retval] double* pRetVal);
    HRESULT Clear();
    HRESULT Add([in] double x);
    HRESULT Subtract([in] double x);
    HRESULT Multiply([in] double x);
    HRESULT Divide([in] double x);
  }
}
Figure 13 Hosting the CLR from Visual Basic
' needs to reference mscorlib.tlb and mscoree.tlb
Dim rt As mscoree.CorRuntimeHost
Dim unk As IUnknown
Dim ad As ComRuntimeLibrary.AppDomain
Dim s As ComRuntimeLibrary.Stack

Private Sub Form_Load()
  Set rt = New mscoree.CorRuntimeHost
  rt.Start
  rt.GetDefaultDomain unk
  Set ad = unk
  Set s = ad.CreateInstance("mscorlib", _
                            "System.Collections.Stack").Unwrap
  s.Push "Hello"
  s.Push "Goodbye"
  s.Push 42
  MsgBox s.Pop()
  MsgBox s.Pop()
  MsgBox s.Pop()
End Sub