How to call Windows function pointers?

Benji Smith dlanguage at benjismith.net
Sat Aug 16 10:59:42 PDT 2008


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


More information about the Digitalmars-d-learn mailing list