[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Literal mimicking of C APIs in Lua (split from Re: [ANN] luaposix 33.3.0 released)
- From: Sean Conner <sean@...>
- Date: Sat, 28 Feb 2015 23:16:51 -0500
It was thus said that the Great Gary V. Vaughan once stated:
> A library binding various POSIX APIs, including curses. POSIX is the IEEE
> Portable Operating System Interface standard. luaposix is based on lposix
> and lcurses.
>
> I am happy to announce release 33.3.0 of luaposix.
This isn't about luaposix per se, but this is prompting this observation
about Lua wrappers for C APIs: they tend to mimic it quite literally (to the
point where I think I've said this before: if I wanted to code in C, I know
where to find it).
I'm not saying that the API luaposix presents should be changed (too much
code probably relies upon the current API) but I will use it to demonstrate
what I mean by literally mimicking the C API.
For instance, syslog(). The C API:
extern void openlog (const char *ident,int option,int facility);
extern void syslog (int priority,const char *format, ... );
extern int setlogmask(int mask);
extern void closelog (void);
It's a fairly simple API of only four functions, and there are a bunch of
integer constants defined for the priority and facility parameters. This
makes sense for C, and a typical call there looks like:
syslog(LOG_WARNING,"foobar %d is at %d capacity",fooid,foocap);
But nearly all syslog modules for Lua are implemented simiarly (include
luaposix) and thus in Lua, the same message would look like:
syslog.syslog(syslog.LOG_WARNING,string.format("foobar %d is at %d capacity",fooid,foocap))
That's a lot of redundant typing.
Now, when I wrote my own wrapper for syslog() several years ago [1], I
followed that approach since it was easiest implementation in C [2]:
static int syslog_syslog(lua_State *L)
{
syslog(luaL_checkinteger(L,1),"%s",luaL_checkstring(L,2));
return 0;
}
It didn't take long for me to get tired of typing:
syslog.syslog(syslog.LOG_WARNING,string.format("foobar %d is at %d capacity",fooid,foocap))
all the time. Slowly, I kept changing the implementation, making it a bit
more complex on the C side, so that it was easier to use in Lua. Now, in
Lua, I can do [3]:
syslog('warning',"foobar %d is at %d capcaity",fooid,foocap)
Yes, the implementatin isn't quite so simple. Yes, I have a metatable on
the returned table with the __call metamethod, so you don't have to call
syslog.syslog() (or syslog.log() as I have it named):
syslog = require "org.conman.syslog"
syslog.open("mythingy",'daemon')
syslog('debug',"Welcome to the machine")
syslog.log('debug',"This also works!")
I only accept strings for the priority and facility (but it's a fixed set of
strings). The syslog module does not contain a list of levels of
facilities. And I have syslog.log() call string.format() for me; it wasn't
that hard:
luaL_checktype(L,2,LUA_TSTRING);
lua_getfield(L,2,"format");
lua_insert(L,2);
lua_call(L,lua_gettop(L) - 2,1);
syslog(level,"%s",lua_tostring(L,-1));
When I look over existing Lua modules like luasocket, luaposix, various
other syslog implementations, I tend to see an almost slavish approach to
mimicking the C API as closely as possible, instead of, for lack of a better
term, Luaizing the API. Another quick example, again, from luaposix,
resource limits:
resource = require "posix.sys.resource"
x = resource.getrlimit(resource.RLIMIT_CORE)
x.rlimit_cur = 1024*1024
resource.setrlimit(resource.RLIMIT_CORE,x)
print(resource.getrlimit(resource.RLIMIT_CORE).rlim_cur)
And the way I solved it [4]:
process = require "org.conman.process"
process.limits.soft.core = "1M" -- 1024*1024 bytes
print(process.limits.soft.core)
Yes, I treat them as variables. I support meaningful suffixes (well, in
strings---you really can't add suffixes to numeric literals).
The thing is---am I alone in doing this? Do I have a different way of
handling C APIs in Lua? Is it more a matter of "following the C API as
directly as possible because of existing documentation"? Or of "this is
easier to do to get this out the door"? Or even "I didn't even think of
doing that"?
-spc (I'm really puzzled over this, as the modules I wrote tend to work
radically different from modules (that cover the same C API) that
others have written ... )
[1] To help me learn the C bindings in Lua.
[2] I don't think my eariest version of this was quite so concise.
[3] https://github.com/spc476/lua-conmanorg/blob/4f129408087f521f1064708813a0469ae6f18b9e/src/syslog.c
[4] https://github.com/spc476/lua-conmanorg/blob/4f129408087f521f1064708813a0469ae6f18b9e/src/process.c#L511