How does lua_val work

, ,

I want to pass a struct with three values (string, int, int) to Lua. No functions. The only example I can find is the Array example, but it only deals with lua_reg and functions.

I managed to create this:

const lua_val helloVal[] = {
	{.name = "txt", .type = kStr, .v.strval = "Hello From C"}
};

static int helloMessage(lua_State *L)
{
	(void)L; // Unused
	pd->lua->pushObject(helloVal, "HelloValues", 0);
	return 1;
}

int eventHandler(PlaydateAPI *playdate, PDSystemEvent event, uint32_t arg)
{
	(void)arg; // Unused
	pd = playdate;
	if (event == kEventInitLua)
	{
		pd->lua->addFunction(helloMessage, "helloMessageFromC", NULL);
		pd->lua->registerClass("HelloValues", NULL, helloVal, 0, NULL);
	}
	return 0;
}

This returns an object I can read the txt field from.

But I can't change the text because it's const.

I have looked at the documentation, but I must admit that I don't quite understand it.

Is there another way I can return a simple struct to Lua?

1 Like

I have tinkered a bit more with it and came up with this:

///main.c
#pragma warning(push, 0) // Disable MSVC warnings in Playdate API
#include "pd_api.h"
#pragma warning(pop) // Enable warnings

PlaydateAPI *pd;
LuaUDObject *luaobj;

lua_val helloVal[] = {
	{.name = "txt", .type = kStr, .v.strval = "Hello From C"},
	NULL};

const lua_val *lvptr = helloVal;

static int helloMessage(lua_State *L)
{
	(void)L; // Unused
	helloVal[0].v.strval = "Hello From Another C String";
	luaobj = pd->lua->pushObject(helloVal, "HelloValues", 1);
	return 1;
}

int eventHandler(PlaydateAPI *playdate, PDSystemEvent event, uint32_t arg)
{
	(void)arg; // Unused
	pd = playdate;
	if (event == kEventInitLua)
	{
		pd->lua->addFunction(helloMessage, "helloMessageFromC", NULL);
		const char *err;
		if (!pd->lua->registerClass("HelloValues", NULL, lvptr, 0, &err))
		{
			pd->system->logToConsole("%s:%i: registerClass failed, %s", __FILE__, __LINE__, err);
		}
	}
	return 0;
}

///main.lua
function playdate.update()
    local helloMessage = helloMessageFromC()
    if helloMessage.txt then
        playdate.graphics.drawText(helloMessage.txt, 10, 10)
    end
end

I have only tried it in the simulator so I don't know if it works on the device. That is not my main concern right now.

So... I have fulfilled the registerClass requirement by using a const lua_val* to a regular lua_val array. This allows me to modify the array values.

If I run this I still get "Hello From C" in the Lua runtime.

With my unfortunately limited understanding of C pointers, the stack and (even more limited knowledge of) how the Playdate C api handles C<->Lua communication I have two questions:

  1. What is happening when calling registerClass? Why is the only value I can read in Lua from when this call was made and not any of the modifications?
  2. If only the values that were present when registering the class, why then do I need to pushObject later? The values at that time are ignored, but if I omit the call I get a stack empty error.