Wednesday, November 23, 2011

Return if

I'd quite like a return-if construction in lua, or at least I'd like to experiment with one.

It would have the form of something like

<return if>  :=  <opt-whitespace> <if> <opt-whitespace> <function>

Then you could do things like

function someFunction()
    local everyThingHasGoneWrong()

    // code
    return if everythingHasGoneWrong()
    // more code
    return if everyThingHasGoneWrong()

The first return arg would be a bool for the if, the second and all those after would be the returns. I'm sure there would be some interesting recursive snippets you could do.

Friday, September 16, 2011

Asynchronous non blocking curl multi example in C++

The curl documentation makes me want to cry.

The library seems nice enough and if you want to do some blocking synchronous http requests (and print them out to the standard out) then it's extremely straight forward.

But who wants to do blocking requests? There are very few programs that can get away with locking entirely until a http request is done.

Also one my internet pet-peeves, when searching for solutions I often come upon threads or mailing lists with someone stating my exact problem and then a reply saying read the docs. It would be so much nicer, internet, if the question had been answered right there and then.

Anyway here's the rough equivalent of simple.c in the examples but using the multi interface so it doesn't block.

The header.
class Http
 CURLM* multi_handle; 
 int handle_count;

  void Update();
  void AddRequest(const char* uri);

The implementation.
 multi_handle = curl_multi_init();
 handle_count = 0;


void Http::Update()
 curl_multi_perform(multi_handle, &handle_count);

void Http::AddRequest(const char* uri)
  CURL* curl = NULL;
  curl = curl_easy_init();
  curl_easy_setopt(curl, CURLOPT_URL, uri);
  curl_multi_add_handle(multi_handle, curl);

First thing to note - the curl pointer is never released! That needs to be taken care of.

The code can be used like

Http http;

// In some update loop called each frame
That will then print the google homepage out to the standard out. Also a good guide to building Curllib can be found here:

Thursday, September 15, 2011

SOIL Great little image loading library

After messing around with dds textures for far too long I found SOIL. Simple OpenGL image loading library, and it is.

	int channels = 0;
	unsigned char* image = SOIL_load_image
		&width, &height, &channels,

	if(image == NULL)
		isLoaded = false;

	GLuint tex_2d =SOIL_create_OGL_texture
		width, height, channels,


My use case is a little more complicated than the examples on the page but only because I wanted the height and width info. This handles the OpenGL Y inversion problem and dds files that have no mip maps which were the ones I was testing with.

Very nice and easy to add statically.

Also while I was debugging my problem I noticed gDebugger is now free and it works very nicely.

Friday, September 09, 2011

Lua and C++ Binding

I've been playing around with Lua lately. When lua code is executed it runs on a lua state (a c struct called lua_State). The lua state contains all the information lua needs - the variables, functions etc. All that is stored in the lua state. You can have several lua states if you want to nicely separate some functionality. Multithreaded programs will generally have a lua state per thread.

I'm using C++ and I have a C++ class the contains a lua state. So if you instantiate a number of these classes, they all have their own lua state.

class SomeClass
    lua_State* mState;
    void SomeFunction();

The thing that becomes fiddly with this approach is that you can't directly bind SomeFunction to the lua state. Lua only binds to free-floating functions or static functions. This makes sense if you think about, it needs a memory address to a function. You could get the memory address of the SomeClass::SomeFunction function - but you wouldn't be able to tell what object it was associated with, you also need the "this" address of the object instance.

One of the first places you might come across this - is the panic function. The panic function is the function the lua_State calls if your lua code breaks.

    mLuaState = lua_open();
    lua_atpanic(mLuaState, panic);

This is in the .cpp file. The lua_atpanic function takes in a lua state and a function. The function is called when the lua code has some kind of problem - the code breaking due to some syntax usually.

The panic function is also defined in the .cpp file but just as a free floating function (this probably isn't the correct terminology but I can't remember what is!).

int panic(lua_State* state)
    // Report error!
    return 0;

Ok so easy enough - we can do the error reporting in the panic function - but how do we know which instance of SomeClass has had the error? Imagine we wanted to print out "Error with lua state in instance named [ConsoleSystem]", how would we know the name of the particular instance?

Well some how we need to associate the lua_State with the instance of the SomeClass class. Remember earlier we were talking about how lua_State is a collection of all the functions and variables of a Lua state? Well we can just add the instance of SomeClass into the state! Genius!

There are a number of places the variables can be added into a lua_State and the most obvious is the globals table.

lua_pushlightuserdata(mLuaState, (void *)this);
lua_setglobal(mLuaState, "__this");

(I haven't tested this code but you get the idea :))

This will do the job, the lua_State now has a global called __this which is a pointer to the SomeClass object that contains it. We can get the pointer back using lua_getglobal.

But I don't like the idea of adding it to the lua globals table because you then have this __this variable there hanging around in the global namespace. If you did

for k, v in pairs(_G) do
    print (k, v)

Then __this would pop up. I think it would be nicer if we could avoid polluting the global namespace but still get the same result.

Lua has a number of tables, not just the globals one - there is also a table called the registry table. Let's add it there.

    mLuaState = lua_open();
    lua_atpanic(mLuaState, panic);
    lua_pushliteral(mLuaState, "this"); 
    lua_pushlightuserdata(mLuaState, (void *)this); 
    lua_settable(mLuaState, LUA_REGISTRYINDEX); /* registry["this"] = this */

Right so we've added a pointer to the SomeClass object into the mLuaState registry table, which is invisible from the lua side.

Now we can rewrite the panic function.

int panic(lua_State* state)
    // Report error!
    lua_pushliteral(state, "this"); 
    lua_gettable(state, LUA_REGISTRYINDEX);
    SomeClass* someClass = (Minigame*)lua_touserdata(state, -1);
    // Now we have access to the instance of the class so we could call something like
    // someClass->Panic(); or

    return 0;

(I also haven't tested any of this code :) And I'm not sure if this is a abuse / misuse of the registry table!) And there you have it, pretty cool, a nice way to bind a lua_State to object instance.

Saturday, June 18, 2011

Oh python

print {True: "hello", 1: "good bye"}

This does not print what I'd expect.

{True: goodbye}

True isn't a special case? It's just a typedef to 1. >_< How do Json importers handle this type of thing?

Edit: Apparently Json doesn't have number keys. Unfortunately this doesn't really fix my problem.

Thursday, May 19, 2011

Excel Wrapper Dot Net

I hate working with Excel files, especially in C#. This wrapper makes things a little easier.

But if you want to save as an xlsx rather than an xlxm then you'll get this error

"This extension can not be used with the selected file type. Change the file extension in the File name text box or select a different file type by changing the Save as type."

This is because in the source code, in the function SaveAs2007 it has the save coder written as:
            workbook.SaveAs(fullPath, 52,
                    missing, missing, false, false, Excel.XlSaveAsAccessMode.xlNoChange,
                    missing, missing, missing, missing, missing);

Change that 52 to a 51 and it will work.