Calling API functions


#1

Hi,

Have never used Julia before. For my friend (who uses Julia), I was attempting to provide an example of using API functions to enum the top level window names, which I have done before in other languages.

I managed to get a valid handle to User32.dll and the entry point of EnumWindows using Base.Libdl, but wasn’t able to successfully call the function.

Having spent a couple of hours investigating Julia I came up with this:

function EnumWindowsProc(title::Ptr,param::Int)
   #TODO: list the returned window names
   return 1
end

lpEnumFunc=cfunction(EnumWindowsProc,Cint,(Ptr{Cstring},Cint))

println(ccall((:EnumWindows,"USER32"),UInt32,(lpEnumFunc,0)))

… which obviously doesn’t work :frowning:

Would be very grateful if anyone can show me where I’m going wrong. Thanks :slight_smile:


#2

Please quote your code :slight_smile:

Looking at https://msdn.microsoft.com/en-us/library/windows/desktop/ms633498(v=vs.85).aspx the type of the cfunction should be lpEnumFunc(EnumWindowsProc, Cint, (Cint, Int)) since HWND is defined as a int and LPARAM is either a __int32 or __int64.

What part doesn’t work for you? What kind of error are you getting? I am :penguin: only.


#3

Thanks for replying. I dont know what a (penguin emoji) is but thanks.

Julia is throwing: “ccall: wrong number of arguments to C function”, which confused me as EnumWindows definately has 2 args. I thought perhaps I might have to supply a prototype of some kind IDK.

Yes, you are quite right, EnumWindow passes a hWnd to EnumWindowsProc, which then should to be passed to GetWindowText to get the title - apologies I was just doing this example from memory and skipped that step, however AFAIK it hasn’t yet come into play as I still can’t call EnumWindows.

I also found at stackoverflow post suggesting that the calling convetion (stdcall) should also be an arg to ccall but I assume that syntax has been removed (tried it… didn’t work)


#4

The penguin is the mascot of Linux.

Your ccallis missing the type signature. It should be something like.

ccall(..., Cint, (Ptr{Void}, Cint), ptr, 0). And once you have that changing the calling convention should also work.


#5

No, it’s still there and still required for most functions in the windows API.


#6

… oh that penguin ofc silly me. Thanks @vchuravy I had the ccall the syntax wrong, this allowed me to call EnumWindows:

function EnumWindowsProc(hWnd::Int32,param::Int32)
   return 1
end

lpEnumFunc=cfunction(EnumWindowsProc,Cint,(Int32,Int32))
println(ccall((:EnumWindows,"USER32"),UInt32,(Ptr{Void},Cint),lpEnumFunc,0))

it happily returns 1 (success) :slight_smile:

Thanks for the info @Keno it complained about the stdcall earlier but that was no doubt just because the other ccall args were wrong. It seems to be defaulting to stdcall anyway so all is well.


#7

See also https://github.com/ihnorton/Win32GUIDemo.jl (needs updating for a few changes, but the ‘ccall’s should all be fine).