Call Win32 API function?

Hello!

Is it possible to call a Win32 API function on Windows? (native, not wsl). Should I use FFI? e.g. how would you call Win32 API MessageBox?

Thanks!

I’m not very familiar with Windows programming, but I’m pretty sure the Win32 API is a C++ API. You’d need to either have a C wrapper for it, or maybe Microsoft already supplies this (or maybe it’s a C API already? Again, I’m not a Windows programmer ^_^)

When you have the C wrapper, you can use the usual lib keyword to make C bindings so Crystal can access it. Something similar to, but not exactly like, this:

@[Link("windows")]
lib LibWin32
  alias HWND = Void*
  fun messageBox = "MessageBox"(handle : HWND, text : UInt8*, caption : UInt8*, typ : LibC::UInt) : LibC::Int
end

LibWin32.messageBox(nil, "Hello, world!", "Hello", 0)

This code won’t work if you copy-paste it, but it might give you a starting point.

EDIT: Actually, I think Win32 already is a C API.

2 Likes

It’s almost there. This works:

@[Link("User32")]
lib LibUser32
  alias HWND = Void*
  fun messageBoxExA = "MessageBoxExA"(handle : HWND, text : UInt8*, caption : UInt8*, typ : LibC::UInt, languageId : LibC::DWORD) : LibC::Int
end

LibUser32.messageBoxExA(nil, "Hello, world!", "Hello", 0, 0)

MessageBox seems to be unavailable in my library (maybe it’s only available in the dll?), but MessageBoxExA or MessageBoxExW work.

3 Likes

If A and W variants exist then the one without either is always a C macro that expands to one of them depending on #ifdef UNICODE.

4 Likes