Oggi ho scoperto un interessante aggiunta alla classe Marshal di System.InteropServices nel Framework 2.0, ovvero il metodo GetDelegateForFunctionPointer.
Questo metodo permette di castare un puntatore a funzione verso un delegate compatibile con la firma della funzione target, aprendo perciò la strada al dynamic P-Invoke.


Questo esempio (fatto volutamente in VB... ) dimostra come sfruttare tale metodo...

Imports System.Runtime.InteropServices
Module Demo
  '//Win32 functions
  "kernel32")> Public Function LoadLibrary(ByVal dllName As String) As IntPtr
  End Function
  "kernel32")> Public Function GetProcAddress(ByVal hModule As IntPtr, ByVal procName As String) As IntPtr
  End Function
  "kernel32")> Public Function FreeLibrary(ByVal hModule As IntPtr) As Boolean
  End Function

  '//Delegate definition
  Public Delegate Function sndPlaySound(<MarshalAs(UnmanagedType.LPWStr)> ByVal name As String, ByVal sound As UInt32) As Boolean

  Sub Main()
    '//Load library containing sndPlaySound
    Dim hModule As IntPtr = LoadLibrary("winmm.dll")
    '//Get fn pointer to sndPlaySound (Unicode)
    Dim ptr As IntPtr = GetProcAddress(hModule, "sndPlaySoundW")
    '//Cast fn Pointer to a compatible delegate
    Dim fn As sndPlaySound = TryCast(Marshal.GetDelegateForFunctionPointer(ptr, GetType(sndPlaySound)), sndPlaySound)
    '//Play sound syncronously
    fn("c:\windows\media\tada.wav", &H20000)
    '//Discard loaded library
    If (FreeLibrary(hModule)) Then
    
Console.WriteLine("Library successfully discarded")
    Else
    
Console.WriteLine("Failed to discard library")
    End If
  End Sub
End
Module

Ovviamente esiste anche GetFunctionPointerForDelegate().
Anche se non credo sia una funzionalità che utilizzeremo tutti i giorni, sopratutto con l'avvento di WinFx, come diceva una vecchia pubblicità: "E' bello sapere che c'è...."