# Callback to WinAPI

**URL:** <https://discourse.julialang.org/t/callback-to-winapi/1381>\
**Category:** General Usage\
**Tags:** windows, ccall\
**Created:** [January 10, 2017, 5:54am UTC](https://discourse.julialang.org/t/callback-to-winapi/1381 "2017-01-10T05:54:29Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![phlavenk](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/phlavenk/32/1873_2.png) [@phlavenk](https://discourse.julialang.org/u/phlavenk)\
**Post date:** [January 10, 2017, 5:54am UTC](https://discourse.julialang.org/t/callback-to-winapi/1381/1 "2017-01-10T05:54:29Z")

</div>

Hi,  
I’m trying to rewrite the following code from  
[https://sjohannes.wordpress.com/2012/03/23/win32-python-getting-all-window-titles/](https://sjohannes.wordpress.com/2012/03/23/win32-python-getting-all-window-titles/)  
from Python to Julia

```
import ctypes

EnumWindows = ctypes.windll.user32.EnumWindows
EnumWindowsProc = ctypes.WINFUNCTYPE(ctypes.c_bool, ctypes.POINTER(ctypes.c_int), ctypes.POINTER(ctypes.c_int))
GetWindowText = ctypes.windll.user32.GetWindowTextW
GetWindowTextLength = ctypes.windll.user32.GetWindowTextLengthW
IsWindowVisible = ctypes.windll.user32.IsWindowVisible

titles = []
def foreach_window(hwnd, lParam):
    if IsWindowVisible(hwnd):
        length = GetWindowTextLength(hwnd)
        buff = ctypes.create_unicode_buffer(length + 1)
        GetWindowText(hwnd, buff, length + 1)
        titles.append(buff.value)
    return True
EnumWindows(EnumWindowsProc(foreach_window), 0)
print(titles)

```

The code lists titles of all currently visible windows.  
I’m struggling with how to specify the stdcall calling convention for the callback function. In a simple ccall one can specify the calling convention

```
tickCount = ccall( (:GetTickCount, "kernel32"), stdcall, UInt32, () )

```

but for callback, the function pointer created by `cfunction` has no calling convention property. Is such functionality available?

Cheers,  
Petr

---

<div class="post-metadata">

**Author:** ![ihnorton](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ihnorton/32/26_2.png) [@ihnorton](https://discourse.julialang.org/u/ihnorton)\
**Post date:** [January 10, 2017, 7:02am UTC](https://discourse.julialang.org/t/callback-to-winapi/1381/2 "2017-01-10T07:02:51Z")

</div>

> [@phlavenk](#):
>
> Is such functionality available?

No, calling convention specification is not supported for `cfunction`. But calling conventions are [unified on 64-bit Windows](https://en.wikipedia.org/wiki/X86_calling_conventions#Microsoft_x64_calling_convention) so this won’t matter unless you are on 32-bit Windows.

see also: [stdcall with cfunction? · Issue #5613 · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/issues/5613)

---

<div class="post-metadata">

**Author:** ![phlavenk](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/phlavenk/32/1873_2.png) [@phlavenk](https://discourse.julialang.org/u/phlavenk)\
**Post date:** [January 10, 2017, 7:45am UTC](https://discourse.julialang.org/t/callback-to-winapi/1381/3 "2017-01-10T07:45:25Z")

</div>

@ihnorton Thank you for the explanation. Still my attempt crashes julia:

```
function foreach_window{T}(hwnd::T, lParam::T)
   return convert(Cint, 1)::Cint
end
const windowEnumCallback = cfunction(foreach_window, Cint, (Ref{Cint}, Ref{Cint}))
ccall((:EnumWindows, "User32"), stdcall, Cint, (Ptr{Void}, Ptr{Cint}), windowEnumCallback, Ref{Cint}(0))

```

the signatures are

> **[EnumWindows function (winuser.h) - Win32 apps](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-enumwindows?redirectedfrom=MSDN)**
>
> Enumerates all top-level windows on the screen by passing the handle to each window, in turn, to an application-defined callback function. EnumWindows continues until the last top-level window is enumerated or the callback function returns FALSE.

```
BOOL WINAPI EnumWindows(
  _In_ WNDENUMPROC lpEnumFunc,
  _In_ LPARAM lParam
);
BOOL CALLBACK EnumWindowsProc(
  _In_ HWND hwnd,
  _In_ LPARAM lParam
);

```

---

<div class="post-metadata">

**Author:** ![Tem\_Pl](https://avatars.discourse-cdn.com/v4/letter/t/8dc957/32.png) [@Tem\_Pl](https://discourse.julialang.org/u/Tem_Pl)\
**Post date:** [January 10, 2017, 3:41pm UTC](https://discourse.julialang.org/t/callback-to-winapi/1381/4 "2017-01-10T15:41:16Z")

</div>

I’m also interested.

---

<div class="post-metadata">

**Author:** ![ihnorton](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ihnorton/32/26_2.png) [@ihnorton](https://discourse.julialang.org/u/ihnorton)\
**Post date:** [January 10, 2017, 11:32pm UTC](https://discourse.julialang.org/t/callback-to-winapi/1381/5 "2017-01-10T23:32:06Z")

</div>

Please review the C interface section of the manual. There are a few problems, such as:

- the `cfunction` signature must match the function declaration
- `Ref` is Julia-owned memory, so it doesn’t make sense in the `cfunction` signature
- `foreach_window` should not be parameterized by type (`{T}`)
- passing a `Ref{Cint}(0)` to `EnumWindows` doesn’t make sense – it’s just a long.

The code below works; hopefully enough to get you going:

```julia
typealias HANDLE Ptr{Void}
typealias LPARAM Clong

handles = HANDLE[]

function foreach_window(hwnd::HANDLE, lParam::LPARAM)
    push!(handles, hwnd)
    return convert(Cint, 1)::Cint
end
const windowEnumCallback = cfunction(foreach_window, Cint, (HANDLE, LPARAM))

ccall((:EnumWindows, "User32"), stdcall, Cint, (Ptr{Void}, LPARAM), windowEnumCallback, 0)

```

(I have some old demo code [here](https://github.com/ihnorton/COMCall.jl) that might be helpful – although I have no idea if it works at all in current Julia)

---

<div class="post-metadata">

**Author:** ![phlavenk](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/phlavenk/32/1873_2.png) [@phlavenk](https://discourse.julialang.org/u/phlavenk)\
**Post date:** [January 11, 2017, 11:03am UTC](https://discourse.julialang.org/t/callback-to-winapi/1381/6 "2017-01-11T11:03:46Z")

</div>

Works great, thank you Isaiah. Making clarification in manual.
