Crying Over Spilt Pointers…

Playing with Lua these past few months, and LuaJIT in particular, has spoiled me as a programmer! After playing around with BanateCAD and HeadsUp, I have finally reached the point where I want to make some standalone executables that don’t require the user to download a version of Lua just to run my scripts.

To that end, I have to go back and write some ‘C’ code, on Windows.

Programming in C on Windows, if you’re using Visual Studio, is actually not that bad. There’s a lot of magic that happens for you, and you’ll never need to know/worry about command line arguments, but if you don’t want to follow that path, life gets very interesting.

I’m starting with creating HeadsUp.exe. That is a standalone application that has the core capabilities of the HeadsUp Program:

  • Brings up a default window
  • Has a GL Context built in
  • Has a frame clock built in
  • Has a standard gaming loop built in
  • Hands keyboard/mouse events to your application script
  • Will call your “draw()” method if you have one

With this set of basics, you can create quite a few simple to complex UI applications from script fairly easily.

The core application is written in about 450 lines of standard Windows code.  In those lines, I have to take care of

  • Register Window Class
  • Create Window
  • Create GL Context
  • Create Lua State
  • Load Lua State with initial setup script

All somewhat straight forward tasks, if taken bit by bit. Along the way, I ran into several little gotchas, since I don’t actually program Windows in straight C these days.

First of all are the various idiosyncracies of programming in C vs C++ vs Lua. First habbit that I’ve formed using Lua is not terminating each statement with ‘;’. In Lua it’s not required, or rather, it’s optional, in most cases. In ‘C’ it’s an absolute MUST. I think I’ll start using ‘;’ more often in my Lua code, since it typically doesn’t hurt, and it makes moving back and forth easier.

The other thing has to do with the usage of parenthesis. In Lua, I can get away with not using them most of the time.

if a  and b then 
    dosomething()
end

In C, it’s you have to be more explicity about things:

if (a && b) {
    dosomething();
}

Then, of course there’s memory management. In C, you are way worried about memory, where’s it’s allocated, when it’s freed, when it’s gone astray. Let’s say I have a function to return the directory path of my application. In Lua, I’d probably do something mindlessly simple:

function GetAppDirectory()
    return getappdirsomehow()
end
.
.
.
local appdir = GetAppDirectory()
print(appdir)

And that would be the end of it. In C, you have to be a bit more mindful:

int GetAppDirectory(char *buff, int bufflen)
{
   int nChars = somesystemcalltogetappdirectory(buff, bufflen)
   buff[nChars] = '';
   return nChars;
}
.
.
.

char buff[MAX_PATH];
int nChars = GetAppDirectory(buff, MAX_PATH-1);
if (nChars > 0)
    printf("Path: %s\n", buff);

A couple of bits are gratuitous in there, but the primary point is that I have to allocate that buffer, on the stack, or otherwise, and more tightly control it’s lifetime.

There is one stream of thought that went into creating the application as an executable, and not have it popup a console window when it launches. There are two things I had to do. First of all, the code itself must have a “WinMain” function, which is what the C runtime looks for if you’re going to launch a Windows application, without a console. Mine looks like this:

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR cmdLine, int nCmdShow)
{
    main(__argc, __argv)
}

The C runtime is nice enough to stick the standard argc, argv parameters into these nice runtime dependent constants __argc, __argv. Then, I go ahead and implement all the guts in my “main()”. This is rather nice for debugging. When I want to use a console window, and get some output, I simply comment out the WinMain(), and let the runtime start with the main() instead. When I want to actually release the code, I’ll uncomment the WinMain, and get the “console less” behavior. Of course, a better way would be to have a runtime flag that allows me to specify a console or not, but then I have to really deal with command line arguments, and that’s been a black art for as long as I’ve been programming.

It’s all fine and good to launch HeadsUp.exe and get a window displayed on the screen, but what can you do with it? Well, first of all, you want to pass the name of the script to actually be executed along to something that will execute that script.

A little prep work here goes a long way. When I startup HeadsUp.exe, it looks for a file “StartUp.lua”, and if it finds that, it will run it in the Lua script engine that it has already created. This script acts as the glue between the C environment and the Lua environment of the script. One of the things I need to do is pass along the name of the script to be executed (specified when HeadsUp.exe was launched).

The way the luajit.exe program does it is to create a table with the name “arg” and stick in whatever parameters were passed on the command line. Since I only have a single parameter, the name of the script, I’m taking a shortcut. It basically looks like this on the C side:

lua_newtable(L);
if (fname != NULL)
{
    lua_pushnumber(L, 1);
    lua_pushstring(L, fname);
    lua_settable(L,-3);
}
lua_setglobal(L, "arg");

dofile(L, "StartUp.lua");

Roughly speaking, create a new table, if there is a filename, then add it to the table at the position ‘1’. Set a global variable named “arg” to be the table with the single entry.

Then, from the lua side, I can do this:

if arg[1] ~= nil then loadfile(arg[1]) end

That’s handy. So, basically, you can use HeadsUp.exe just like you’d use wluajit.exe, or equivalent, with the exception that it already has some goodness baked in (GL Context, timer, event loop).

There are a couple of hooks that come along as well. The StartUp.lua needs a way to be notified of a few things that are occuring on the C side. They are:

  • Mouse Activity
  • Keyboard Activity
  • Window Resizing
  • Tick Count

Well, since I’m using LuaJIT, these look like simple candidates for some callbacks. So, first on the C side, I put the following into the HeadsUpMain.h file:

#define DllExport __declspec(dllexport)
#define DllImport __declspec(dllimport)

#ifdef __cplusplus
extern "C" {
#endif

#include 

typedef void (*OnResizedDelegate)(int newWidth, int newHeight);
typedef void (*OnTickDelegate)(int tickCount);
typedef void (*MsgReceiver)(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);

DllExport int RegisterTickDelegate(OnTickDelegate delegate);
DllExport int RegisterKeyboardMouse(MsgReceiver receiver);
DllExport int RegisterResizedDelegate(OnResizedDelegate delegate);

#ifdef __cplusplus
}
#endif

There are what I’d consider a couple of magic incantations here. First of all, there’s the DllExport macro. That’s to ensure that these functions will be “exported”. That is, if you use the dumpbin /EXPORTS command, you’ll see these entries show up as accessible from the .exe. What that means is that I can then use ffi.load(“HeadsUp.exe”) to gain access to functions that I’ve exported from the application. Neat trick eh? This way I don’t have a separate .dll floating around. The application IS the .dll.

Of course, there’s that magical:
#ifdef __cplusplus
extern “C” {
#endif

The thing is, with C++ (the .cpp file) will generate these nicely ‘mangled’ names, which are not easily comprehended by the LuaJIT ffi, or any other ffi for that matter. By wrapping them in ‘extern “C”‘, I’m ensuring that the names will stay sane, and be exactly what I said they would be. Very necessary.

Then, on the Lua side of things, I define some standard ffi interop goodness:

local HUP = ffi.load("HeadsUp.exe")

ffi.cdef[[
typedef void (*OnResizedDelegate)(int newWidth, int newHeight);
typedef void (*OnTickDelegate)(int tickCount);
typedef void (*MsgReceiver)(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);

int RegisterKeyboardMouse(MsgReceiver receiver);
int RegisterResizedDelegate(OnResizedDelegate delegate);
int RegisterTickDelegate(OnTickDelegate delegate);
]]

Basically just three functions that I want to deal with. In order to use these, I do the following:

function OnWindowResized(width, height)
    windowWidth = width;
    windowHeight = height;
end

HUP.RegisterResizedDelegate(OnWindowResized);

So, basically, whenever the window is resized, my OnWindowResized() function will be called, and I can do whatever it is that I want to do when the window resizes.

Same goes for the OnTick(), and OnKeyboardMouse(). OnKeyboardMouse() is a bit different in that raw windows parameters are handed in. I do it this way because I want the Lua side to decide when/whether to create any objects to represent events.

Well, that’s about it. Basic C based executable with all the necessities to get a fundamental OpenGL app up and running. The glue code required to go between the two worlds, and everything else is pure Lua again.

It’s been an interesting reeducation in the usage of C on Windows. The good news is, at 450 lines of code, there’s a fairly minimal surface area to deal with. This bodes well for the equivalent Linux of MacOS versions of the same.

Now that I have the basic framework, it will be relatively easy to hang things like the thread creation and networking calls, while the Lua code stays fairly platform agnostic.



Leave a comment