[Date Prev][Date Next][Thread Prev][Thread Next]
- Subject: Re: Help writing my first Lua C module
- From: David Crayford <dcrayford@...>
- Date: Mon, 30 Sep 2013 19:26:59 +0800
On 28/09/2013 5:06 PM, Philipp Janda wrote:
Am 27.09.2013 14:50 schröbte David Crayford:
// ISPF API functions.
typedef int (isplink_t)();
typedef int (ispexec_t)( size_t, const char * );
isplink_t * isplink;
ispexec_t * ispexec;
// load ISPLINK/ISPEXEC services
api.isplink = ( isplink_t * ) fetch("ISPLINK");
api.ispexec = ( ispexec_t * ) fetch("ISPEXEC");
Can you call `fetch("ISPLINK")` multiple times? Do you need to
unregister those services (once, or for every fetch call)? Is `api`
really a global, or is this sample code?
Is it better to return the API as userdata or create a table? I'm a
neophyte so bear with me.
Lua cannot represent or use a generic function pointer on the Lua side
(other than as a void pointer), so there *will* be a userdata involved
anyway. I'd go for a single full userdata storing the api struct (or a
pointer to it if api is a global variable) and a metatable +
__index-table for the methods.
In your special case you could also create your methods as closures
which store the userdata as an upvalue, and return a table containing
those closuses. As a consequence you could (but wouldn't need to) use
the alternative syntax `ispf.exec("DISPLAY PANEL(P)")`, and you could
omit some type checking inside the methods.
That's the direction I took and it works great. I snatched a version of
luaL_setfuncs() from lua-cjson which done the trick.
And number three is: Wrap each function pointer in a separate userdata
(inside a struct to be ANSI C compatible) and set the __call
metamethod. You could return a table having an __index function to
load your services on-demand ...
I want to be able to do something like this
ispf = require("ispf")
while ispf:exec("DISPLAY PANEL(P)") == 0 do
-- process the panel
This is pretty standard stuff (with the possible exception that your
module seems to be some sort of singleton), but maybe you want your
`exec` function to return a boolean (+ additional return values)
instead of a number ...
The number is a return code from the service. It can be 0, 4, 8, 12 or
20 depending on the call. I plan to write abstraction layers on top to
make it more usable.
And relying on `require` to only load your module once is not safe! If
someone resets `package.loaded.ispf`, and `require`s your module
again, your module will be loaded a second time.