lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


I like this idea, I've downloaded the tarball and I will try it out.
I agree with Misko that you should keep a very bare, minimal setup.
Lua's C API is simple enough as such things go.

Anyway, cool idea!

Cheers,
Ben

On Mon, Jun 2, 2008 at 8:14 AM, Martin <wtxnh-lua@yahoo.com.au> wrote:
> On Mon, Jun 02, 2008 at 06:06:50PM +0900, YutakaUeno wrote:
>>
>> This is a result of my experiment for an easyer API, tentatively named
>> as EasyLua, as a simpler way to embed Lua into a C-program, not C++.
>> While the formal C-API is just fine, but this is a subset for beginers.
>> The main idea of my method is to minimize thinking about the lua-stack
>> on accessing Lua data from a C-program.
>> It was deviced after I was wondering if we can use following way to
>> refer Lua values from a C language.
>>
>>   int nframe_inlua   = el_num(el_var("nframe"));
>>   char * title_inlua = el_str(el_var("title"));
>>
>> Here, the function el_var() will keep the name of the global variable
>> on the stack, then on calling el_num(), it invokes
>> lua_gettable(L,GLOBALSINDEX) and calls lua_tonumber().
>
> To make it even simpler I would suggest to hide el_val() function from
> user. So one can write:
>   int nframe_inlua = el_num("nframe");
>   char * title_inlua = el_str("title");
>
>> For writing a value into Lua, it might be following way.
>>
>>   el_setnum(el_var("nframe"), 100);
>
> Similarly for setting variable:
>    el_setnum("nframe", 100);
>
>> For these two ways for reading and writing, we just need to maintain
>> the stack contents properly using the return value of el_var().
>> Using two stack elements, table and index can be specified.
>> So, I would like to access a field in a Lua table
>> like following way. First, the table is assigned an integer
>> handle, in this sample, number 2 is assigned.
>>
>>   el_table(2,"user");
>>   el_num(el_field(2,"uid");
>>   el_setnum(el_field(2,"uid"),9601); /** user.uid=9601 **/
>
> For setting fields in table I would suggest:
>    el_table_setnum("user", "uid", 9601);
>    el_table_setstring("user", "name", "my_own_name");
>
> Similarly for fetching fields from table:
>    int uid = el_table_num("user", "uid");
>    char * name = el_table_string("user", "name");
>
>> Is it simple enough for beginers?
>
> I thing that introducing integer handle would unnecessary confuse
> _beginner_ users. Users more experienced should anyway use
> standard API.
>
>> Since most of program in my work is a standalone program that will
>> only use several of Lua variables, including a few tables.
>> Probably there are discussions for this method, and improvements
>> are needed. This method is less efficient as the formal API, but
>> it is much more comprehensive. This EasyLua API does not
>> provide full set of functionality yet.
>> Again, this subset API is to lower the hardle for beginers.
>> For those who understand the formal C-API of Lua, it will
>> be better to use the formal one.
>
> Yes, I guess some users that need only limited portion
> of usability of embedded lua will agree to trade efficiency
> for ease of use. But you should than emphasize very loudly and
> very often in manual for your implementation that it is just
> simplified and very reduced set of lua. I would think  very hard
> if there should be implemented any more than this 8 functions:
>    el_num
>    el_setnum
>    el_table_num
>    el_table_setnum
>    el_string
>    el_setstring
>    el_table_string
>    el_table_setstring
> Naturally you need to provide something like this too:
>    el_luaopen() // create new lua state and assign it to
>                 // global variable that all other functions refer to
>    el_luaclose()  // close above created lua state
>    el_loadfile("my_script.lua") // load and execute script file
>
> And of course you need to handle errors in some graceful way in all
> of your functions (if that is possible in general way). There are
> two ways I can think of:
>  - ignore all errors (not very good, I guess)
>  - exit the application (not very user friendly)
>
> If user need more functionality there should be strong warning
> that it is needed to use standard API and not to mix easy_lua
> API with standard one. If facilities provided with easy_lua
> are enough for task under the hand than OK, if you need more
> do not use easy_lua at all!
>
>> Is there already such a method used by somebody?
>> My implementation is uploaded on my site:
>> http://www.cbrc.jp/~ueno/devzone/ezlua01.tgz
>>
>> It is still experimental, but I would be happy if people test
>> and examine. In this implementation, the name of global variables
>> or filed name was saved in the Lua stack, and they are cleaned
>> after a value is obtained. Calling Lua function is a bit tricky
>> because the Lua stack have to be used for the argument and
>> return values. EasyLua takes a table for return values.
>>
>>   ip=el_var("print");
>>   el_pushnum("something");    /** the same as official API **/
>>   el_pushstr(10.0);
>>   ir=el_call(ip);
>>   el_num(el_index(ir,1)));      /** if return values exist **/
>
> This is one example where I think that your proposed easy_lua API
> does not bring anything simpler to user than there already is.
> Normally it would be written (without error checking!) as:
>  lua_getglobal(L, "my_func");
>  lua_pushstring(L, "something");
>  lua_pushnumber(L, 10.0);
>  lua_pcall(L, 2, 1, 0);
>  double num = lua_tonumber(L, -1);
> It is basically line for line replacement and I do not think that
> is of any benefit (on the other hand it can be confusing for beginner
> in that way that it bring two alternative way to do the same thing:
> one of which is official way and the other one that is no simpler
> than first one.
>
> If you want to simplify function call you should restrict yourself
> only to most common cases. Something like this:
>     double el_num_call_num(double arg);
>     char * el_string_call_string(char * arg);
> perhaps even:
>     double el_num_call_string(char * arg);
>     char * el_string_call_num(double arg);
> or some other combinations that you find most needed. But do
> not get carried and implement lot of combination (more than
> one argument of different types, function that return more
> than one value etc...)
>
> Note that even accessors to table are crippled:
> values stored and fetched can be only numbers and strings, not
> booleans, function, tables ... Also keys are only string, not all
> the other types (numbers are used very often for example).
>
> For your proposed approach to function calling I have
> some observations/questions:
> - it seems you swapped arguments for el_pushnum and el_pushstr
> - standard function print actually does not return any value
>  (but you have covered that case with comment at last line
>  so it is ok)
> - in function el_index what is meaning of second argument?
>
>> Any comments are welcome.
>> ---
>> Yutaka Ueno
>
> Again to repeat myself. I think you should limit yourself to
> implement only very small set of functions that will cover
> most often used cases of storing and fetching values form
> global variables and tables. If you will try to every feature
> (or lot more than accessing variables and perhaps call to simple
> functions) my belief is that it will be not easy API anymore. It
> will be just different than the official one. And that will do
> no good to anyone.
>
> Misko
>