This will go a bit further as it will pass values to and from the lua code.
It uses less of the SWIG code, and more of the raw lua API's
What it will do is load the wrapped lib, load runme.lua and then call some functions.
To make life easier, all the printf's have either [C] or [Lua] at the start
so you can see where they are coming from.
We will be using the luaL_dostring()/lua_dostring() function to call into lua
*/
#if !defined(SWIG_NO_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE)
# define _CRT_SECURE_NO_DEPRECATE
#endif
#if !defined(SWIG_NO_SCL_SECURE_NO_DEPRECATE) && defined(_MSC_VER) && !defined(_SCL_SECURE_NO_DEPRECATE)
# define _SCL_SECURE_NO_DEPRECATE
#endif
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
#include <stdarg.h>
#include <string.h>
#if LUA_VERSION_NUM > 501
#define lua_open luaL_newstate
#endif
extern int luaopen_example(lua_State*L);
int add(int,int)
it's very tedious, but gives you an idea of the issues involved.
(look below for a better idea)
*/
int call_add(lua_State *L,int a,int b,int* res) {
int top;
push a, push b, call 'add' check & return res
*/
top=lua_gettop(L);
lua_getglobal(L, "add");
if (!lua_isfunction(L,-1)) {
printf("[C] error: cannot find function 'add'\n");
lua_settop(L,top);
return 0;
}
lua_pushnumber(L,a);
lua_pushnumber(L,b);
if (lua_pcall(L, 2, 1, 0) != 0)
{
printf("[C] error running function `add': %s\n",lua_tostring(L, -1));
lua_settop(L,top);
return 0;
}
if (!lua_isnumber(L,-1)) {
printf("[C] error: returned value is not a number\n");
lua_settop(L,top);
return 0;
}
*res=(int)lua_tonumber(L,-1);
lua_settop(L,top);
return 1;
}
Original Code from Programming in Lua (PIL) by Roberto Ierusalimschy
ISBN 85-903798-1-7
http://www.lua.org/pil/25.3.html
This has been modified slightly to make it compile, and it's still a bit rough.
But it gives the idea of how to make it work.
*/
int call_va (lua_State *L,const char *func, const char *sig, ...) {
va_list vl;
int narg, nres;
int top;
top=lua_gettop(L);
va_start(vl, sig);
lua_getglobal(L, func);
narg = 0;
while (*sig) {
switch (*sig++) {
case 'd':
lua_pushnumber(L, va_arg(vl, double));
break;
case 'i':
lua_pushnumber(L, va_arg(vl, int));
break;
case 's':
lua_pushstring(L, va_arg(vl, char *));
break;
case '>':
goto endwhile;
default:
printf("invalid option (%c)\n", *(sig - 1));
goto fail;
}
narg++;
}
endwhile:
nres = (int)strlen(sig);
if (lua_pcall(L, narg, nres, 0) != 0)
{
printf("error running function `%s': %s\n",func, lua_tostring(L, -1));
goto fail;
}
nres = -nres;
while (*sig) {
switch (*sig++) {
case 'd':
if (!lua_isnumber(L, nres)) {
printf("wrong result type\n");
goto fail;
}
*va_arg(vl, double *) = lua_tonumber(L, nres);
break;
case 'i':
if (!lua_isnumber(L, nres)) {
printf("wrong result type\n");
goto fail;
}
*va_arg(vl, int *) = (int)lua_tonumber(L, nres);
break;
case 's':
if (!lua_isstring(L, nres)) {
printf("wrong result type\n");
goto fail;
}
strcpy(va_arg(vl, char *),lua_tostring(L, nres));
break;
default: {
printf("invalid option (%c)", *(sig - 1));
goto fail;
}
}
nres++;
}
va_end(vl);
lua_settop(L,top);
return 1;
fail:
lua_settop(L,top);
return 0;
}
int main(int argc,char* argv[]) {
lua_State *L;
int ok;
int res;
char str[80];
printf("[C] Welcome to the simple embedded Lua example v2\n");
printf("[C] We are in C\n");
printf("[C] opening a Lua state & loading the libraries\n");
L=lua_open();
luaopen_base(L);
luaopen_string(L);
luaopen_math(L);
printf("[C] now loading the SWIG wrapped library\n");
luaopen_example(L);
printf("[C] all looks ok\n");
printf("\n");
if (argc != 2 || argv[1] == NULL || strlen(argv[1]) == 0) {
printf("[C] ERROR: no lua file given on command line\n");
exit(3);
}
printf("[C] let's load the file '%s'\n", argv[1]);
printf("[C] any lua code in this file will be executed\n");
if (luaL_loadfile(L, argv[1]) || lua_pcall(L, 0, 0, 0)) {
printf("[C] ERROR: cannot run lua file: %s",lua_tostring(L, -1));
exit(3);
}
printf("[C] We are now back in C, all looks ok\n");
printf("\n");
printf("[C] let's call the Lua function 'add(1,1)'\n");
printf("[C] using the C function 'call_add'\n");
ok=call_add(L,1,1,&res);
printf("[C] the function returned %d with value %d\n",ok,res);
printf("\n");
printf("[C] let's do this rather easier\n");
printf("[C] we will call the same Lua function using a generic C function 'call_va'\n");
ok=call_va(L,"add","ii>i",1,1,&res);
printf("[C] the function returned %d with value %d\n",ok,res);
printf("\n");
printf("[C] we will now use the same generic C function to call 'append(\"cat\",\"dog\")'\n");
ok=call_va(L,"append","ss>s","cat","dog",str);
printf("[C] the function returned %d with value %s\n",ok,str);
printf("\n");
printf("[C] we can also make some bad calls to ensure the code doesn't fail\n");
printf("[C] calling adds(1,2)\n");
ok=call_va(L,"adds","ii>i",1,2,&res);
printf("[C] the function returned %d with value %d\n",ok,res);
printf("[C] calling add(1,'fred')\n");
ok=call_va(L,"add","is>i",1,"fred",&res);
printf("[C] the function returned %d with value %d\n",ok,res);
printf("\n");
printf("[C] Note: no protection if you mess up the va-args, this is C\n");
printf("\n");
printf("[C] Finally we will call the wrapped gcd function gdc(6,9):\n");
printf("[C] This will pass the values to Lua, then call the wrapped function\n");
printf(" Which will get the values from Lua, call the C code \n");
printf(" and return the value to Lua and eventually back to C\n");
printf("[C] Certainly not the best way to do it :-)\n");
ok=call_va(L,"gcd","ii>i",6,9,&res);
printf("[C] the function returned %d with value %d\n",ok,res);
printf("\n");
printf("[C] all finished, closing the lua state\n");
lua_close(L);
return 0;
}