Skip to content
This repository was archived by the owner on Jul 1, 2020. It is now read-only.

Commit 15b840c

Browse files
Added glfw_base.lua. Improved build script. Added readme.
1 parent 572bc37 commit 15b840c

File tree

6 files changed

+289
-4
lines changed

6 files changed

+289
-4
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
__pycache__
2+
glfw.lua

build.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
2+
set -e
3+
gcc -E -dD -I ./gen/ ./gen/headers.h | python3 ./gen/cdef.py | cat - glfw_base.lua > glfw.lua

gen/cdef.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@
6666
cdefs.append(line.replace(r'__attribute__((__stdcall__)) ', ''))
6767

6868
# Output the file
69-
#print("--[[ AUTOGENERATED FILE, DO NOT MODIFY ]]")
69+
print("--[[ BEGIN AUTOGENERATED SEGMENT ]]")
7070
print("local glc; do require('ffi').cdef [[")
7171
for line in cdefs:
7272
print("\t", line, sep="")
@@ -76,3 +76,4 @@
7676
print("\t%s = %s," % ("['"+k+"']", defines[k]))
7777

7878
print("} end")
79+
print("--[[ END AUTOGENERATED SEGMENT ]]")

gen/cdefgen.sh

Lines changed: 0 additions & 3 deletions
This file was deleted.

glfw_base.lua

Lines changed: 247 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,247 @@
1+
2+
assert(glc, "luajit-glfw was not built properly.")
3+
local ffi = require "ffi"
4+
local jit = require "jit"
5+
6+
local Lib = {}
7+
8+
-- Load and export libraries
9+
local gl, glu, glfw
10+
if ffi.os == "Windows" then
11+
gl = ffi.load("opengl32")
12+
glu = ffi.load("glu32")
13+
else
14+
gl = ffi.load("GL")
15+
glu = ffi.load("GLU")
16+
end
17+
glfw = ffi.load("glfw3")
18+
19+
Lib.gl = gl
20+
Lib.glc = glc
21+
Lib.glu = glu
22+
Lib.glfw = glfw
23+
24+
-- Export a metatable for automatically loading extension functions
25+
Lib.glext = setmetatable({}, {
26+
__index = function(self, k)
27+
local ok, typ = pcall(ffi.typeof, string.format("PFN%sPROC", string.upper(k)))
28+
if not ok then error("Couldn't find pointer type for "..k.." (are you accessing the right function?)",2) end
29+
30+
local ptr = ffi.cast(typ, glfw.glfwGetProcAddress(k))
31+
if ptr == nil then error("Unable to load function: "..k, 2) end
32+
33+
rawset(Lib.glext, k, ptr)
34+
35+
return ptr
36+
end,
37+
})
38+
39+
-- TODO: The docs say that `lib.foo` is faster than `local foo = lib.foo; foo()`, but is the overhead of a closure
40+
-- worth it?
41+
local function wrap(lib, fname)
42+
return function(...)
43+
return lib[fname](...)
44+
end
45+
end
46+
47+
local int_buffer = ffi.new("int[2]")
48+
local double_buffer = ffi.new("double[2]")
49+
50+
---------------------------------------------------------------------------------------------------------------------
51+
-- GLFW Global Functions
52+
53+
-- C functions that don't need special handling
54+
Lib.terminate = wrap(glfw, "glfwTerminate")
55+
56+
Lib.getTime = wrap(glfw, "glfwGetTime")
57+
Lib.setTime = wrap(glfw, "glfwSetTime")
58+
Lib.defaultWindowHints = wrap(glfw, "glfwDefaultWindowHints")
59+
Lib.swapInterval = wrap(glfw, "glfwSwapInterval")
60+
Lib.getCurrentContext = wrap(glfw, "glfwGetCurrentContext")
61+
Lib.getProcAddress = wrap(glfw, "glfwGetProcAddress")
62+
Lib.joystickPresent = wrap(glfw, "glfwJoystickPresent")
63+
64+
-- Functions with special Lua code
65+
66+
-- Throws an error on failure
67+
function Lib.init()
68+
if glfw.glfwInit() ~= 0 then
69+
error("glfwInit failed",0)
70+
end
71+
end
72+
73+
-- Returns true/false
74+
function Lib.extensionSupported(name) return glfw.glfwExtensionSupported(name) ~= 0 end
75+
76+
-- Returns three integers instead of out parameters
77+
function Lib.glfwVersion()
78+
local buffer = ffi.new("int[3]")
79+
glfw.glfwGetVersion(buffer, buffer+1, buffer+2)
80+
return buffer[0], buffer[1], buffer[2]
81+
end
82+
83+
-- Converts the returned strung to a Lua string
84+
function Lib.glfwVersionString()
85+
return ffi.string(glfw.glfwGetVersionString())
86+
end
87+
88+
-- Allocates or fills a table and fills it with the results.
89+
function Lib.getJoystickAxes(joy, arr)
90+
arr = arr or {}
91+
local values = glfw.glfwGetJoystickAxes(joy, int_buffer)
92+
if values == nil then error("Invalid joystick: "..joy, 2) end
93+
for i=0,int_buffer[0]-1 do
94+
arr[i+1] = values[i]
95+
end
96+
return arr
97+
end
98+
99+
-- Allocates or fills a table and fills it with the results.
100+
function Lib.getJoystickButtons(joy, arr)
101+
arr = arr or {}
102+
local values = glfw.glfwGetJoystickButtons(joy, int_buffer)
103+
if values == nil then error("Invalid joystick: "..joy, 2) end
104+
for i=0,int_buffer[0]-1 do
105+
arr[i+1] = values[i]
106+
end
107+
return arr
108+
end
109+
110+
function Lib.getJoystickName(joy)
111+
local name = glfw.glfwGetJoystickName(joy)
112+
if name == nil then error("Invalid joystick: "..joy, 2) end
113+
return ffi.string(name)
114+
end
115+
116+
function Lib.getMonitors()
117+
local cmonitors = glfw.glfwGetMonitors(int_buffer)
118+
if cmonitors == nil then error("glfwGetMonitors failed",2) end
119+
120+
local monitors = {}
121+
for i=0,int_buffer[0]-1 do
122+
monitors[i+1] = cmonitors[i]
123+
end
124+
return monitors
125+
end
126+
127+
function Lib.getPrimaryMonitor()
128+
local monitor = glfw.glfwGetPrimaryMonitor()
129+
if monitor == nil then error("glfwGetPrimaryMonitor failed",2) end
130+
return monitor
131+
end
132+
133+
---------------------------------------------------------------------------------------------------------------------
134+
-- Window
135+
136+
local Window = {}
137+
Window.__index = Window
138+
local Window_t = ffi.typeof("GLFWwindow")
139+
Lib.Window = Window_t
140+
141+
function Window:__new(w, h, title, monitor, share)
142+
local window = glfw.glfwCreateWindow(w,h,title,monitor,share)
143+
if window == nil then error("glfwCreateWindow failed", 2) end
144+
return window
145+
end
146+
147+
-- C functions that don't need special handling
148+
Window.destroy = wrap(glfw, "glfwDestroyWindow")
149+
Window.getAttrib = wrap(glfw, "glfwGetWindowAttrib")
150+
Window.getMonitor = wrap(glfw, "glfwGetWindowMonitor")
151+
Window.hide = wrap(glfw, "glfwHideWindow")
152+
Window.iconify = wrap(glfw, "glfwIconifyWindow")
153+
Window.restore = wrap(glfw, "glfwRestoreWindow")
154+
Window.setPos = wrap(glfw, "glfwSetWindowPos")
155+
Window.setShouldClose = wrap(glfw, "glfwSetWindowShouldClose")
156+
Window.setSize = wrap(glfw, "glfwSetWindowSize")
157+
Window.setTitle = wrap(glfw, "glfwSetWindowTitle")
158+
Window.show = wrap(glfw, "glfwShowWindow")
159+
Window.hint = wrap(glfw, "glfwWindowHint")
160+
Window.shouldClose = wrap(glfw, "glfwWindowShouldClose")
161+
Window.makeContextCurrent = wrap(glfw, "glfwMakeContextCurrent")
162+
Window.swapBuffers = wrap(glfw, "glfwSwapBuffers")
163+
Window.setClipboardString = wrap(glfw, "glfwSetClipboardString")
164+
Window.getInputMode = wrap(glfw, "glfwGetInputMode")
165+
Window.setInputMode = wrap(glfw, "glfwSetInputMode")
166+
Window.getKey = wrap(glfw, "glfwGetKey")
167+
Window.getMouseButton = wrap(glfw, "glfwGetMouseButton")
168+
Window.setCursorPos = wrap(glfw, "glfwSetCursorPos")
169+
Window.setFramebufferSizeCallback = wrap(glfw, "glfwSetFramebufferSizeCallback")
170+
Window.setCloseCallback = wrap(glfw, "glfwSetWindowCloseCallback")
171+
Window.setFocusCallback = wrap(glfw, "glfwSetWindowFocusCallback")
172+
Window.setIconifyCallback = wrap(glfw, "glfwSetWindowIconifyCallback")
173+
Window.setPosCallback = wrap(glfw, "glfwSetWindowPosCallback")
174+
Window.setRefreshCallback = wrap(glfw, "glfwSetWindowRefreshCallback")
175+
Window.setSizeCallback = wrap(glfw, "glfwSetWindowSizeCallback")
176+
Window.setKeyCallback = wrap(glfw, "glfwSetKeyCallback")
177+
Window.setCharCallback = wrap(glfw, "glfwSetCharCallback")
178+
Window.setMouseButtonCallback = wrap(glfw, "glfwSetMouseButtonCallback")
179+
Window.setCursorPosCallback = wrap(glfw, "glfwSetCursorPosCallback")
180+
Window.setCursorEnterCallback = wrap(glfw, "glfwSetCursorEnterCallback")
181+
Window.setScrollCallback = wrap(glfw, "glfwSetScrollCallback")
182+
183+
-- These functions can't be jit compiled, because they may call callbacks.
184+
-- Don't use wrap because jit.off affects the prototype, which will affect other functions too.
185+
Window.pollEvents = function(self) return glfw.glfwPollEvents(self) end
186+
jit.off(Window.pollEvents)
187+
188+
Window.waitEvents = function(self) return glfw.glfwWaitEvents(self) end
189+
jit.off(Window.waitEvents)
190+
191+
-- Functions with special Lua code
192+
193+
-- Returns width, height instead of needing out parameters
194+
function Window:getFramebufferSize()
195+
glfw.glfwGetFramebufferSize(self, int_buffer, int_buffer+1)
196+
return int_buffer[0], int_buffer[1]
197+
end
198+
199+
-- Returns width, height instead of needing out parameters
200+
function Window:getSize()
201+
glfw.glfwGetWindowSize(self, int_buffer, int_buffer+1)
202+
return int_buffer[0], int_buffer[1]
203+
end
204+
205+
-- Returns x, y instead of needing out parameters
206+
function Window:getPos()
207+
glfw.glfwGetWindowPos(self, int_buffer, int_buffer+1)
208+
return int_buffer[0], int_buffer[1]
209+
end
210+
211+
-- Converts the returned strung to a Lua string
212+
function Window:getClipboardString()
213+
return ffi.string(glfw.glfwGetClipboardString(self))
214+
end
215+
216+
-- Returns x, y instead of needing out parameters
217+
function Window:getCursorPos()
218+
glfw.glfwGetCursorPos(self, double_buffer, double_buffer+1)
219+
return double_buffer[0], double_buffer[1]
220+
end
221+
222+
ffi.metatype(Window_t, Window)
223+
224+
---------------------------------------------------------------------------------------------------------------------
225+
-- Monitor
226+
227+
local Monitor = {}
228+
Monitor.__index = Monitor
229+
local Monitor_t = ffi.typeof("GLFWmonitor")
230+
Lib.Monitor = Monitor_t
231+
232+
Monitor.setCallback = wrap(glfw, "glfwSetMonitorCallback")
233+
234+
function Monitor:getPos()
235+
glfw.glfwGetMonitorPos(self, int_buffer, int_buffer+1)
236+
return int_buffer[0], int_buffer[1]
237+
end
238+
239+
function Monitor:getPhysicalSize()
240+
glfw.glfwGetMonitorPhysicalSize(self, int_buffer, int_buffer+1)
241+
return int_buffer[0], int_buffer[1]
242+
end
243+
244+
ffi.metatype(Monitor_t, Monitor)
245+
246+
---------------------------------------------------------------------------------------------------------------------
247+
return Lib

readme.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
2+
LuaJIT-GLFW
3+
===========
4+
5+
LuaJIT FFI bindings for GLFW 3 and OpenGL.
6+
7+
This library contains everything needed to start a basic OpenGL app in Lua.
8+
9+
Building
10+
--------
11+
12+
LuaJIT-GLFW builds bindings from the systems OpenGL and GLFW headers, as well as an included `glext.h` file.
13+
To build the bindings, you need to have `gcc` as well as headers for OpenGL and GLFW installed, though the resulting
14+
file should be cross-platform compatible.
15+
16+
To build, just run `build.sh` in the repository directory. This will create a `glfw.lua` file, which is the only file
17+
you need to install.
18+
19+
Usage
20+
-----
21+
22+
To load the library, use the `require` function:
23+
24+
```lua
25+
local glfw = require "glfw"
26+
```
27+
28+
LuaJIT-GLFW loads the following libraries:
29+
30+
* `glfw.gl`: OpenGL
31+
* `glfw.glu`: GLU
32+
* `glfw.glfw`: GLFW
33+
* `glfw.glext`: A table that, when indexed, loads the specified extension function.
34+
* `glfw.glc`: `#define`d values for OpenGL and GLFW (this must be a Lua table instead of `static const` values, because OpenGL uses `longs` in a couple of places)
35+
36+
Additionally, LuaJIT-GLFW wraps GLFW functions and structs for convenience. See `glfw_base.lua`

0 commit comments

Comments
 (0)