#!/usr/bin/luaClearly the complexity is all on the C side, because the Lua side is simple. The preceding code has a require("power") statement to load a module called "power", and obviously that module has functions square() and cube(). So the C program not only has to define functions square() and cube(), but must register itself as a module and register those two functions so that they're visible to Lua.
require("power")
print(square(1.414213598))
print(cube(5))
int luaopen_power(lua_State *L){Its only argument is a Lua state variable, and for each C function it wants made available to Lua it must call lua_register(). The lua_register() function takes three arguments:
lua_register(
L, /* Lua state variable */
"square", /* func name as known in Lua */
isquare /* func name in this file */
);
lua_register(L,"cube",icube);
return 0;
}
static int isquare(lua_State *L){ /* Internal name of func */A function runnable in Lua always has the same prototype -- a Lua state variable argument, and it returns a static int. That return value is the number of items it's returning.
float rtrn = lua_tonumber(L, -1); /* Get the single number arg */
printf("Top of square(), nbr=%f\n",rtrn);
lua_pushnumber(L,rtrn*rtrn); /* Push the return */
return 1; /* One return value */
}
slitt@mydesk:~$ gcc -Wall -shared -fPIC -o power.so -I/usr/include/lua5.1 -llua5.1 hellofunc.cHere's what the preceding means:
slitt@mydesk:~$
ARG |
MEANING |
|
gcc |
The compiler |
|
-Wall |
Warn on almost anything |
|
-shared |
Compile to .so format, and don't error out just because there's no main() |
|
-fPIC |
Goes with -shared to tell the executable format. Subtle errors can sometimes creep in if you don't do this. |
|
-o power.so |
Name the shared library power.so |
|
-I/usr/include/lua5.1 |
Look for lua.h etc in /usr/include/lua5.1. Note this will be different on every system. |
|
-llua5.1 |
Compile with the Lua library. Note this will be different on every system. See here for how you deduce the -l argument. |
|
hellofunc.c |
The source file to the power library. It doesn't have to be named "power". |
/* hellofunc.c (C) 2011 by Steve LittCompile the preceding with the following command:
* gcc -Wall -shared -fPIC -o power.so -I/usr/include/lua5.1 -llua5.1 hellofunc.c
* Note the word "power" matches the string after the underscore in
* function luaopen_power(). This is a must.
* The -shared arg lets it compile to .so format.
* The -fPIC is for certain situations and harmless in others.
* On your computer, the -I and -l args will probably be different.
*/
#include <lua.h> /* Always include this */
#include <lauxlib.h> /* Always include this */
#include <lualib.h> /* Always include this */
static int isquare(lua_State *L){ /* Internal name of func */
float rtrn = lua_tonumber(L, -1); /* Get the single number arg */
printf("Top of square(), nbr=%f\n",rtrn);
lua_pushnumber(L,rtrn*rtrn); /* Push the return */
return 1; /* One return value */
}
static int icube(lua_State *L){ /* Internal name of func */
float rtrn = lua_tonumber(L, -1); /* Get the single number arg */
printf("Top of cube(), number=%f\n",rtrn);
lua_pushnumber(L,rtrn*rtrn*rtrn); /* Push the return */
return 1; /* One return value */
}
/* Register this file's functions with the
* luaopen_libraryname() function, where libraryname
* is the name of the compiled .so output. In other words
* it's the filename (but not extension) after the -o
* in the cc command.
*
* So for instance, if your cc command has -o power.so then
* this function would be called luaopen_power().
*
* This function should contain lua_register() commands for
* each function you want available from Lua.
*
*/
int luaopen_power(lua_State *L){
lua_register(
L, /* Lua state variable */
"square", /* func name as known in Lua */
isquare /* func name in this file */
);
lua_register(L,"cube",icube);
return 0;
}
gcc -Wall -shared -fPIC -o power.so -I/usr/include/lua5.1 -llua5.1 hellofunc.cNow refer to it with hellofunc.lua:
#!/usr/bin/luaAnd then run hellofunc.lua:
require("power")
print(square(1.414213598))
print(cube(5))
slitt@mydesk:~$ ./hellofunc.luaBang! It worked!
Top of square(), nbr=1.414214
2.0000002687177
Top of cube(), number=5.000000
125
slitt@mydesk:~$
/*Compile it like this:
* gcc -shared -fPIC -o msleep.so -I/usr/include/lua5.1 -llua5.1 msleep.c
* -I and -l may vary on your computer.
* Your computer may use something besides -fPIC
*/
#include <unistd.h>
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
static int msleep_c(lua_State *L){
long msecs = lua_tointeger(L, -1);
usleep(1000*msecs);
return 0; /* No items returned */
}
/* Can't name this sleep(), it conflicts with sleep() in unistd.h */
static int sleep_c(lua_State *L){
long secs = lua_tointeger(L, -1);
sleep(secs);
return 0; /* No items returned */
}
/* Register both functions */
int luaopen_msleep(lua_State *L){
lua_register( L, "msleep", msleep_c);
lua_register(L, "sleep", sleep_c);
return 0;
}
gcc -Wall -shared -fPIC -o msleep.so -I/usr/include/lua5.1 -llua5.1 msleep.cRemember, on your system -I and -l may be different, and possibly your -f might be different.
#!/usr/bin/luaThe preceding code prints out the following, proving that the new functions work:
require("msleep")
p = print
sf = string.format
local start = os.time()
p(sf("Started at %d", start))
sleep(1)
local mid = os.time()
p(sf("After sleep(1), time is %d", mid))
msleep(2000)
local endd = os.time()
p(sf("After msleep(2000), time is %d", endd))
print()
p(sf("First interval = %d seconds.", mid - start))
p(sf("Second interval = %d seconds.", endd - mid))
p(sf("Whole interval = %d seconds.", endd - start))
slitt@mydesk:~$ ./test_msleep.luaThis is just one small example of the beauty of including C functions in your Lua programs.
Started at 1297165088
After sleep(1), time is 1297165089
After msleep(2000), time is 1297165091
First interval = 1 seconds.
Second interval = 2 seconds.
Whole interval = 3 seconds.
slitt@mydesk:~$
[ Troubleshooters.com| Code Corner | Email Steve Litt ]
Copyright
(C) 2011 by Steve Litt --Legal