How to call Windows function pointers?

downs default_357-line at yahoo.de
Sat Aug 16 12:08:30 PDT 2008


downs wrote:
> 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); }

If it doesn't work, try typedef instead.


More information about the Digitalmars-d-learn mailing list