Skip to content

KeyWorksRW/kwxLuaJIT

Repository files navigation

kwxLuaJIT

LuaJIT language bindings for wxWidgets via kwxFFI, enabling cross-platform GUI applications that render with native controls on Windows, macOS, and Linux.

⚠️ Warning: Not Production Ready

Do not use this Lua/wxWidgets interface in production.

  • The kwxFFI ABI interface is not stable and can change without warning.
  • Very little testing has been done, and won't be until late Q2 of 2026.
  • API surface may change as idioms are refined.

Overview

kwxLuaJIT provides a two-layer binding architecture:

  1. FFI Layer (wx/*_gen.lua) — Auto-generated by kwxgen. Raw LuaJIT FFI class wrappers with ffi.cdef declarations mapping directly to kwxFFI C function exports. One file per wxWidgets class.
  2. Wrapper Layer (lua/wx/init.lua) — The wx module. Convenience constructors with sensible defaults, Lua-friendly method overrides, runtime constants, and the event callback bridge.

Users work with the wx module. The generated *_gen.lua files are available for direct access when needed.

Lua code  →  wx module (lua/wx/)  →  *_gen.lua (FFI declarations)  →  kwxFFI (C functions)  →  wxWidgets (C++)

Quick Example

-- examples/hello.lua - Hello World wxWidgets application in Lua

local wx = require("wx")

-- Create application (wxApp is managed by the C++ launcher)
local app = wx.App()

-- Create main frame with standard system buttons
local frame = wx.Frame(nil, "kwxLuaJIT Demo", -1, -1, 800, 600,
                       wx.DEFAULT_FRAME_STYLE)

-- Status bar
frame:CreateStatusBar()
frame:SetStatusText("Welcome to kwxLuaJIT")

-- Panel holds all controls
local panel = wx.Panel(frame)

-- Vertical sizer for layout
local sizer = wx.BoxSizer(wx.VERTICAL)

local label  = wx.StaticText(panel, "Welcome to kwxLuaJIT!")
local button = wx.Button(panel, "Click Me")

-- Connect button click event to a Lua function
button:Connect(wx.EVT_BUTTON, function()
    wx.MessageBox("Hello from Lua!", "kwxLuaJIT")
end)

-- Add controls to sizer
sizer:Add(label,  0, wx.ALL, 10)
sizer:Add(button, 0, wx.ALL + wx.ALIGN_CENTER, 10)
panel:SetSizer(sizer)

frame:Show(true)
frame:Center()
app:MainLoop()

More examples are in the examples/ directory.

Module Structure

Metatable chaining mirrors the wxWidgets C++ class hierarchy. Every object carries a _ptr field (opaque void*) and inherits methods through the chain:

wxEvtHandler
└── wxWindow
    ├── wxTopLevelWindow
    │   ├── wxFrame
    │   └── wxDialog
    ├── wxPanel
    ├── wxButton
    ├── wxStaticText
    ├── wxTextCtrl
    ├── wxCheckBox
    ├── wxChoice
    ├── wxListBox
    └── wxComboBox

wxSizer
├── wxBoxSizer
├── wxFlexGridSizer
└── wxGridSizer

All objects are created through wx.* convenience constructors or the generated *_gen.Create(...) functions directly.

Naming Conventions

Entity Convention Example
User-facing module wx local wx = require("wx")
Generated modules <classname>_gen wxframe_gen, wxbutton_gen
Convenience constructors wx.ClassName(...) wx.Frame(...), wx.Button(...)
Methods PascalCase :Show(), :Connect(), :SetSizer()
Constants wx.CONSTANT_NAME wx.EXPAND, wx.DEFAULT_FRAME_STYLE
Event types wx.EVT_* wx.EVT_BUTTON, wx.EVT_CLOSE
Raw FFI exports expwx<NAME> expwxID_ANY, expEVT_BUTTON

Event Handling

Events are connected with :Connect() (also aliased as :Bind()):

-- Connect a named or anonymous function
button:Connect(wx.EVT_BUTTON, function(evt)
    print("clicked")
end)

-- Disconnect by callback id
local cb_id = button:Connect(wx.EVT_BUTTON, handler)
button:Disconnect(cb_id)

-- Disconnect all handlers for an object
window:DisconnectAll()

Event types are resolved lazily — wx.EVT_BUTTON triggers a single FFI call on first access and is then cached as a plain integer.

Why Lua + wxWidgets?

Lua is widely used for scripting, configuration, and rapid prototyping, but native GUI options are scarce. kwxLuaJIT combines LuaJIT's zero-overhead FFI with wxWidgets' native rendering: one small executable, native look on every supported platform, no separate Lua or wxWidgets installation required.

Compilers & Toolchain

Toolchain Status
MSVC cl.exe (Windows) ✅ Primary
MinGW (Windows) ✅ Supported
GCC (Linux / macOS) 🔧 Planned

LuaJIT is built automatically from source by CMake — no separate installation needed.

Building

Prerequisites:

  • CMake 3.30+
  • A supported C/C++ compiler (see above)
  • Internet access for FetchContent (kwxFFI and wxWidgets are fetched automatically)
# Configure and build (Windows, MSVC)
cmake --preset windows-msvc
cmake --build build --config Debug

# Run an example
.\build\Debug\kwxlua.exe examples\hello.lua

License

Apache License 2.0 — see LICENSE for details.

About

Lua language bindings for wxWidgets

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors