How to call Windows function pointers?

downs default_357-line at yahoo.de
Sat Aug 16 12:07:57 PDT 2008


Benji Smith wrote:
> I'm using tango.sys.SharedLib to dynamically load a DLL and get a
> function pointer to a win32 API function. And that's working nicely. But
> the function pointer is returned as a void*, and to call it, I think I
> need to cast it to a function pointer. But the function needs to be
> called with extern(Windows) calling conventions. At first, I tried this:
> 
> 
>   alias uint BOOL;
>   alias uint DWORD;
>   alias ulong DWORDLONG;
> 
>   struct MEMORYSTATUSEX {
>     DWORD dwLength;
>     DWORD dwMemoryLoad;
>     DWORDLONG ullTotalPhys;
>     DWORDLONG ullAvailPhys;
>     DWORDLONG ullTotalPageFile;
>     DWORDLONG ullAvailPageFile;
>     DWORDLONG ullTotalVirtual;
>     DWORDLONG ullAvailVirtual;
>     DWORDLONG ullAvailExtendedVirtual;
>   }
> 
>   public void callWin32Function() {
>     auto lib = SharedLib.load(`c:\windows\system32\kernel32.dll`);
>     void* sym = lib.getSymbol("GlobalMemoryStatusEx");
>     auto fn = cast(extern(Windows) BOOL function(MEMORYSTATUSEX)) sym;
> 
>     MEMORYSTATUSEX memStatus;
>     fn(memStatus);
>   }
> 
> 
> But the compiler rejects that cast because of the "extern(Windows)" bit.
> 
> Without the cast, it compiles, but throws an Access Violation when I
> call the function pointer, obviously because it's using the wrong
> calling convention.
> 
> I hate to suggest that the calling convention should be part of the type
> system (because the type system is already burdened with too much,
> especially in D2, with const semantics and now thread-sharing
> semantics). But clearly two function pointers with different calling
> conventions are different types of functions, and it seems like the type
> system should take responsibility for ensuring the correct calling
> convention.
> 
> I've also tried this, thinking that declaring "fn" as a member with the
> "extern(Windows)" calling convention would solve the problem:
> 
> 
>   alias uint BOOL;
>   alias uint DWORD;
>   alias ulong DWORDLONG;
> 
>   struct MEMORYSTATUSEX {
>     DWORD dwLength;
>     DWORD dwMemoryLoad;
>     DWORDLONG ullTotalPhys;
>     DWORDLONG ullAvailPhys;
>     DWORDLONG ullTotalPageFile;
>     DWORDLONG ullAvailPageFile;
>     DWORDLONG ullTotalVirtual;
>     DWORDLONG ullAvailVirtual;
>     DWORDLONG ullAvailExtendedVirtual;
>   }
> 
>   extern(Windows) BOOL function(MEMORYSTATUSEX) fn;
> 
>   public void callWin32Function() {
>     auto lib = SharedLib.load(`c:\windows\system32\kernel32.dll`);
>     void* sym = lib.getSymbol("GlobalMemoryStatusEx");
>     fn = cast(BOOL function(MEMORYSTATUSEX)) sym;
> 
>     MEMORYSTATUSEX memStatus;
>     fn(memStatus);
>   }
> 
> 
> But the the compiler still doesn't like that cast. It gives this error:
> 
> cannot implicitly convert expression (cast(uint
> function(MEMORYSTATUSEX))exFunctionPtr) of type uint
> function(MEMORYSTATUSEX) to uintWindows  function(MEMORYSTATUSEX)
> 
> Anyone have any suggestions?
> 
> Thanks!
> 
> --benji

Try this (untested):

template ExtWinType(T) { extern(Windows) alias T ExtWinType; }

void callWin32Fn() { auto lib ...; auto fn = cast(ExtWinType!(BOOL function(MEMORYSTATUSEX))) lib.getSymbol("..."); fn(foo); }


More information about the Digitalmars-d-learn mailing list