4

I'm trying to hide my P/Invoke functions, like this one:

[<DllImport("kernel32.dll", SetLastError=true)>]
extern bool private CreateTimerQueueTimer(IntPtr& phNewTimer, nativeint TimerQueue, WaitOrTimerDelegate Callback, nativeint Parameter, uint32 DueTime, uint32 Period, ExecuteFlags Flags)

Strangely, though, the private gets ignored -- which is really annoying, because I want to hide all the unwieldy structs and enums associated with these functions.

I guess I could put everything in a private module, so it's not too big of a deal, but am I missing something?

Rei Miyasaka
  • 7,007
  • 6
  • 42
  • 69
  • 1
    Smells like a bug; putting these in a private module indeed sounds like the best workaround. – Brian Jun 26 '12 at 22:29
  • 3
    For what it's worth, this sounds like an excellent use case for an interface file (in other words, using a *.fsi file to hide certain elements). – pblasucci Jun 26 '12 at 22:48
  • In what context is your `extern` function right now? Within a class, or? – Anders Gustafsson Jun 27 '12 at 06:32
  • @pblasucci Please, this isn't a "use case". They didn't break access modifier keywords for certain scenarios just to give purpose to another feature. Forgive my tone, but I can't help but be exasperated when people refuse to accept when there's a problem with their favorite languages. It isn't good for the future of the language. – Rei Miyasaka Jun 27 '12 at 13:22
  • @Brian Do you guys have a public bug tracker, or is fsbugs@microsoft.com good? – Rei Miyasaka Jun 27 '12 at 13:36
  • 2
    @ReiMiyasaka: Whoa! take it easy. I didn't say it was or wasn't a bug. I'm not in a position to make that call. I simply suggested a way to solve your problem. Isn't that the point of StackOverflow? – pblasucci Jun 28 '12 at 01:43

1 Answers1

0

This will do the job.

module a =
    [<AbstractClass>]
    type private NativeMethods() =
        [<DllImport("kernel32.dll", EntryPoint="CreateTimerQueueTimer",
                    SetLastError=true)>]
        static extern bool sCreateTimerQueueTimer( (* whatever *) )
        static member CreateTimerQueueTimer = sCreateTimerQueueTimer

    let usedInside = NativeMethods.CreateTimerQueueTimer

module b =
    open a
    // the next line fails to compile
    let usedOutside = NativeMethods.CreateTimerQueueTimer( (* whatever *) )

Notes:

  • private class can be accessed only from the enclosing module, this is what you need, so just wrap the methods in a NativeMethods class;
  • You cannot set your extern method private since it wouldn't be accessible from the rest of module a;
  • extern member of a class is always private, so there's another method with same signature;
  • Finally, use EntryPoint to resolve naming.
Be Brave Be Like Ukraine
  • 7,596
  • 3
  • 42
  • 66