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