Embedding Lua in C by Example

Here is a series of short C snippets to learn how to embed Lua in your C program. The complete source for these examples can be found at: https://github.com/HParker/embedding-lua-in-c-by-example

Run a string of Lua code #

#include <stdio.h>
#include <lauxlib.h>
#include <lua.h>
#include <lualib.h>

int main() {
  // setup lua
  lua_State *L = luaL_newstate();
  luaL_openlibs(L);

  // Run a lua string
  luaL_dostring(L, "print(\"hello from lua\")");
}

Run a file of Lua code #

#include <stdio.h>
#include <lauxlib.h>
#include <lua.h>
#include <lualib.h>

int main() {
  // setup lua
  lua_State *L = luaL_newstate();
  luaL_openlibs(L);

  // run a lua file
  luaL_dofile(L, "hello.lua");
}

Get a number from Lua #

  luaL_dostring(L, "x = 10");
  lua_getglobal(L, "x");
  int x = (int)lua_tonumber(L, -1);
  printf("x = %i\n", x);

Get a string from Lua #

  luaL_dostring(L, "string = 'hi there'");
  lua_getglobal(L, "string");
  const char * string = lua_tolstring(L, -1, NULL);
  printf("string = '%s'\n", string);

Get a table field from Lua #

  luaL_dostring(L, "table = { key = 123 }");
  lua_getglobal(L, "table");
  lua_getfield(L, -1, "key");
  int key = (int)lua_tonumber(L, -1);
  printf("key = %i\n", key);

Call Lua function from C #

  luaL_dostring(L, "function foo() print(\"Hello from foo method\") end");
  lua_getglobal(L, "foo");
  if (lua_isfunction(L, -1)) {
    //                        V number of arguments
    //                        |  V number of results
    int status = lua_pcall(L, 0, 0, 0);
    // status can be LUA_OK, LUA_ERRRUN, LUA_ERRMEM, or LUA_ERRERR
    if (status != LUA_OK) {
      printf("Something went wrong when calling the lua function\n");
    } else {
      int result = (int)lua_tonumber(L, -1);
      printf("result = %i\n", result);
    }
  } else {
    printf("function `foo` was not found or was not a function\n");
  }

Call lua function with a return value from C #

  luaL_dostring(L, "function foo() return 456 end");
  lua_getglobal(L, "foo");
  if (lua_isfunction(L, -1)) {
    //                        V number of arguments
    //                        |  V number of results
    int status = lua_pcall(L, 0, 1, 0);
    // status can be LUA_OK, LUA_ERRRUN, LUA_ERRMEM, or LUA_ERRERR
    if (status != LUA_OK) {
      printf("Something went wrong when calling the lua function\n");
    } else {
      int result = (int)lua_tonumber(L, -1);
      printf("result = %i\n", result);
    }
  } else {
    printf("function `foo` was not found or was not a function\n");
  }

Call a lua function with arguements from C #

  luaL_dostring(L, "function square(x) return x * x end");
  lua_getglobal(L, "square");
  if (lua_isfunction(L, -1)) {
    //                        V number of arguments
    //                        |  V number of results
    lua_pushnumber(L, (lua_Number)5);
    int status = lua_pcall(L, 1, 1, 0);
    // status can be LUA_OK, LUA_ERRRUN, LUA_ERRMEM, or LUA_ERRERR
    if (status != LUA_OK) {
      printf("Something went wrong when calling the lua function\n");
      printf("Error: %s \n", lua_tostring(L, -1));
      lua_pop(L, 1);
    } else {
      int doubled = (int)lua_tonumber(L, -1);
      printf("doubled = %i\n", doubled);
    }
  } else {
    printf("function `square` was not found or was not a function\n");
  }

Expose a C function to Lua #

#include <stdio.h>
#include <lauxlib.h>
#include <lua.h>
#include <lualib.h>

int basicCFunc(lua_State * L) {
  printf("This is my c function called from lua\n");
  return 0; // number of results
}

int main() {
  // setup lua
  lua_State *L = luaL_newstate();
  luaL_openlibs(L);

  lua_register(L, "basicCFunc", basicCFunc);
  luaL_dostring(L, "basicCFunc()");
}

Expose a C function to Lua that returns a value #

#include <stdio.h>
#include <lauxlib.h>
#include <lua.h>
#include <lualib.h>

int returningCFunc(lua_State * L) {
  lua_pushnumber(L, 678); // result
  return 1; // number of results
}

int main() {
  // setup lua
  lua_State *L = luaL_newstate();
  luaL_openlibs(L);

  // expose a function to lua that returns a value
  lua_register(L, "returningCFunc", returningCFunc);
  luaL_dostring(L, "returnedFromC = returningCFunc()");
  lua_getglobal(L, "returnedFromC");
  int returnedFromC = (int)lua_tonumber(L, -1);
  printf("returned from c = %i\n", returnedFromC);
}

Expose a C function to Lua that takes one arguments #

#include <stdio.h>
#include <lauxlib.h>
#include <lua.h>
#include <lualib.h>

int argumentCFunc(lua_State * L) {
  lua_pushnumber(L, lua_tonumber(L, 1) + 1); // result
  return 1; // number of results
}

int main() {
  // setup lua
  lua_State *L = luaL_newstate();
  luaL_openlibs(L);

  lua_register(L, "argumentCFunc", argumentCFunc);
  luaL_dostring(L, "returnedFromC = argumentCFunc(1)");
  lua_getglobal(L, "returnedFromC");
  returnedFromC = (int)lua_tonumber(L, -1);
  printf("returned from c = %i\n", returnedFromC);
}

Expose a C function to Lua that takes any number of arguments #

#include <stdio.h>
#include <lauxlib.h>
#include <lua.h>
#include <lualib.h>

int variableArgumentCFunc(lua_State * L) {
  int n = lua_gettop(L); // number of arguments
  float sum = 0.0;
  int i;
  for (i = 1; i <= n; i++) {
    if (!lua_isnumber(L, i)) {
      lua_pushliteral(L, "incorrect argument");
      lua_error(L);
    }
    sum += lua_tonumber(L, i);
  }
  lua_pushnumber(L, sum); // result
  return 1; // number of results
}

int main() {
  // setup lua
  lua_State *L = luaL_newstate();
  luaL_openlibs(L);

  lua_register(L, "variableArgumentCFunc", variableArgumentCFunc);
  luaL_dostring(L, "returnedFromC = variableArgumentCFunc(1, 2, 3)");
  lua_getglobal(L, "returnedFromC");
  returnedFromC = (int)lua_tonumber(L, -1);
  printf("returned from c = %i\n", returnedFromC);
}
 
2
Kudos
 
2
Kudos

Now read this

Orbtoberfest by CircleCI

CircleCI put on an event in Seattle to promote their open Orb registry. Orbs are their shared configuration format that allows you to write a CircleCI configuration for a job that anyone can use. This was possible before Orbs by sharing... Continue →