Why both of these compilations, but only one of them works?

open System
open System.Diagnostics
open System.Runtime.InteropServices
module PInvoke = 
    type EnumThreadDelegate= delegate of (IntPtr * IntPtr) -> bool
    type ComArrayList() =
        inherit System.Collections.ArrayList() 

    [<DllImport("user32.dll")>]
    extern [<return: MarshalAs(UnmanagedType.Bool)>] bool private EnumThreadWindows(int dwThreadId, EnumThreadDelegate lpfn, IntPtr lParam);
    let getThreadWindows (threadId:int) : _ list = 
        let items = ResizeArray()
        let withData (hWnd:IntPtr, lParam:IntPtr) = 
            let _ = items.Add(hWnd,lParam)
            true
        let f = EnumThreadDelegate withData

        EnumThreadWindows (threadId, f, IntPtr.Zero) |> ignore<bool>
        items
        |> Seq.cast<IntPtr*IntPtr>
        |> List.ofSeq


let lp = Process.GetProcesses() |> Seq.filter(fun p -> p.ProcessName.StartsWith("L")) |> Seq.minBy(fun p -> p.StartTime) 
lp.Threads
|> Seq.cast<ProcessThread> 
|> Seq.map (fun t -> t.Id) 
|> Seq.map PInvoke.getThreadWindows
|> List.ofSeq

      

gives System.Runtime.InteropServices.MarshalDirectiveException: Cannot marshal 'parameter #1': Generic types cannot be marshaled

but this one compiles and runs:

open System
open System.Diagnostics
open System.Runtime.InteropServices
module PInvoke = 
    type EnumThreadDelegate= delegate of IntPtr * IntPtr -> bool
    type ComArrayList() =
        inherit System.Collections.ArrayList() 

    [<DllImport("user32.dll")>]
    extern [<return: MarshalAs(UnmanagedType.Bool)>] bool private EnumThreadWindows(int dwThreadId, EnumThreadDelegate lpfn, IntPtr lParam);
    let getThreadWindows (threadId:int) : _ list = 
        let items = ResizeArray()
        let withData (hWnd:IntPtr) (lParam:IntPtr) = 
            let _ = items.Add(hWnd,lParam)
            true
        let f = EnumThreadDelegate withData

        EnumThreadWindows (threadId, f, IntPtr.Zero) |> ignore<bool>
        items
        |> Seq.cast<IntPtr*IntPtr>
        |> List.ofSeq


let lp = Process.GetProcesses() |> Seq.filter(fun p -> p.ProcessName.StartsWith("L")) |> Seq.minBy(fun p -> p.StartTime) 
lp.Threads
|> Seq.cast<ProcessThread> 
|> Seq.map (fun t -> t.Id) 
|> Seq.map PInvoke.getThreadWindows
|> List.ofSeq

      

why both compile but one gives an exception?

what's the difference between a delegate of (IntPtr*IntPtr) -> bool

and delegate of IntPtr*IntPtr->bool

? shouldn't they be the same? (IntPtr*IntPtr)

does not match with IntPtr*IntPtr

?

+3


source to share


1 answer


I think,

delegate of (IntPtr*IntPtr) -> bool

      

is a delegate with one argument that takes Tuple<IntPtr,IntPtr>

, whereas



delegate of IntPtr*IntPtr -> bool

      

is a two-argument delegate that takes two IntPtr

as two arguments.

+4


source







All Articles