How to acquire the name of the variables passes to the self-defined C function which has been successfully set by lua_register()?

classic Classic list List threaded Threaded
14 messages Options
Reply | Threaded
Open this post in threaded view
|

How to acquire the name of the variables passes to the self-defined C function which has been successfully set by lua_register()?

孙世龙 sunshilong
We can push self-defined C function to lua_register.

But how to acquire the name of the variables passes to the
aforementioned self-defined C function?

I would be grateful to have some help with this question.
Reply | Threaded
Open this post in threaded view
|

Re: How to acquire the name of the variables passes to the self-defined C function which has been successfully set by lua_register()?

Sean Conner
It was thus said that the Great 孙世龙 sunshilong once stated:
> We can push self-defined C function to lua_register.
>
> But how to acquire the name of the variables passes to the
> aforementioned self-defined C function?
>
> I would be grateful to have some help with this question.

  Assuming I have a function foo() that's been defined in C and
lua_register() has been called on it, what should the names of the variables
be in the following cases?

        foo(3)
        foo("a simple string")
        foo(true)
        foo({ 1 , 2 , 3 , 4 })

  Second question:  what are you hoping to do with such information?

  -spc

Reply | Threaded
Open this post in threaded view
|

Re:How to acquire the name of the variables passes to the self-defined C function which has been successfully set by lua_register()?

suote127
In reply to this post by 孙世龙 sunshilong
It seems impossible.
Lua will push all the arguments into the stack when we call a C function.We can only access the arguments by indexes.
If it is possible to do it,it will also be useless.
Reply | Threaded
Open this post in threaded view
|

Re: How to acquire the name of the variables passes to the self-defined C function which has been successfully set by lua_register()?

Philippe Verdy-2
shouldn't "lua_register" allow specifying names in the Lua-to-C bindings, so that positional (integer indexed) parameters would have a name (and possibly a formal type description) if parameters C function has static datatypes (not varargs), and some datatype conversions could occur when needed (e.g. converting a Lua "number" to a C "short", or "float", or "double", or a Lua "string" to some of the string datatypes supported in C such as "char*" where Lua would allocate a copy of the string, possibly also supported charsets conversion to UTF-8, or UTF-16 or a windows OEM charset, possibly lossy with fallbacks, or could authorize to pass the internal buffer if the C function uses it as a "const char*", i.e. with a supposedly readonly buffer, and avoid the extra cost to the memory allocator and complications to the garbage collector, or could use alloca() to allocate writable short strings in the "C" call stack itself).
The interface between Lua and C should offer better flexibility for the bindings, with additional performance benefits (but possibly security problems to solve). If we compare to what is sone in Java, JNI passes all strings using copies to temporary buffers allocated externally, the problem being that the binding must be also flexible enough to know when to free that buffer, if the C function wants to keep that buffer internally and does not reallocate its own local copy out of the memory pool managed by the JVM: this is important if such buffers are used to perform asynchronous requests that will still run when the "C" function returns or that will be reused later when an event handler will need these buffers, possibly in another thread, or in another process via some shared memory like a memory-mapped file or some RPC/LPC mechanism of the OS; it's hard to cleanly separate the memory pools and isolate the sandboxes to secure them: binding can be quite complex, the alternative being to define a very restrictive ABI restricting the datatypes we can pass to C and restricting as well their lifecycle.)



Le mer. 20 janv. 2021 à 11:20, Suote127 <[hidden email]> a écrit :
It seems impossible.
Lua will push all the arguments into the stack when we call a C function.We can only access the arguments by indexes.
If it is possible to do it,it will also be useless.
Reply | Threaded
Open this post in threaded view
|

Re: How to acquire the name of the variables passes to the self-defined C function which has been successfully set by lua_register()?

孙世龙 sunshilong
In reply to this post by Sean Conner
>what are you hoping to do with such information?
I want to give the users more accurate error message to accelerate the
debugging process.
For example, if the value provided by the user is out of range, I hope
to tell the user the variable named 'foo' is invalid(instead of
telling them the first or second parameter is invalid).

On Wed, Jan 20, 2021 at 5:29 PM Sean Conner <[hidden email]> wrote:

>
> It was thus said that the Great 孙世龙 sunshilong once stated:
> > We can push self-defined C function to lua_register.
> >
> > But how to acquire the name of the variables passes to the
> > aforementioned self-defined C function?
> >
> > I would be grateful to have some help with this question.
>
>   Assuming I have a function foo() that's been defined in C and
> lua_register() has been called on it, what should the names of the variables
> be in the following cases?
>
>         foo(3)
>         foo("a simple string")
>         foo(true)
>         foo({ 1 , 2 , 3 , 4 })
>
>   Second question:  what are you hoping to do with such information?
>
>   -spc
>
Reply | Threaded
Open this post in threaded view
|

Re: How to acquire the name of the variables passes to the self-defined C function which has been successfully set by lua_register()?

Sean Conner
It was thus said that the Great 孙世龙 sunshilong once stated:
> >what are you hoping to do with such information?
> I want to give the users more accurate error message to accelerate the
> debugging process.
> For example, if the value provided by the user is out of range, I hope
> to tell the user the variable named 'foo' is invalid(instead of
> telling them the first or second parameter is invalid).

  What's wrong with error()?  

        local function foo(x)
          if x < 1 or x > 10 then
            error('paramter "x" is out of range')
          end
       
          return x + 3
        end
       
        foo(0)

[spc]lucy:/tmp>lua e.lua
lua: e.lua:4: paramter "x" is out of range
stack traceback:
        [C]: in function 'error'
        e.lua:4: in local 'foo'
        e.lua:10: in main chunk
        [C]: in ?
[spc]lucy:/tmp>

It shows which named parameter was invalid, plus the call stack showing
where it was called in context.  If throwing an error is not to your liking,
you could also do:

        local function foo(x)
          if x < 1 or x > 10 then
            return nil,debug.traceback('parameter "x" is out of range')
          end

          return x + 3
        end

to mimic the common Lua idiom of returning nil plus an error message.

  -spc
Reply | Threaded
Open this post in threaded view
|

Re: How to acquire the name of the variables passes to the self-defined C function which has been successfully set by lua_register()?

孙世龙 sunshilong
>What's wrong with error()?
Sorry for my poor English.
I would show you a simple example, please pay attention to the comments.

//C code.
int self_def_func(struct lua_State* L)
{
    int argc =  lua_gettop(L);

    int type = lua_type(L, 1);
    if(type != LUA_TNUMBER)
    {
         // I hope to tell the exact name of the parameter that passed
to the self-defined function.
        luaL_error(L, "the variable named XX should be a int or double");
    }
    else
    {
        double val = lua_tonumber(L, 1);
        if(var>100)
        {
              // I hope to tell the exact name of the parameter that
passed to the self-defined function.
              luaL_error(L, "the variable named XX is out of range");
        }
     }
  }

int main()
{
     ...
     lua_register(L,  self_def_func);
}

--lua code
temperature = 150;
loc = "test"
self_def_func(temperature, loc)

On Thu, Jan 21, 2021 at 11:48 AM Sean Conner <[hidden email]> wrote:

>
> It was thus said that the Great 孙世龙 sunshilong once stated:
> > >what are you hoping to do with such information?
> > I want to give the users more accurate error message to accelerate the
> > debugging process.
> > For example, if the value provided by the user is out of range, I hope
> > to tell the user the variable named 'foo' is invalid(instead of
> > telling them the first or second parameter is invalid).
>
>   What's wrong with error()?
>
>         local function foo(x)
>           if x < 1 or x > 10 then
>             error('paramter "x" is out of range')
>           end
>
>           return x + 3
>         end
>
>         foo(0)
>
> [spc]lucy:/tmp>lua e.lua
> lua: e.lua:4: paramter "x" is out of range
> stack traceback:
>         [C]: in function 'error'
>         e.lua:4: in local 'foo'
>         e.lua:10: in main chunk
>         [C]: in ?
> [spc]lucy:/tmp>
>
> It shows which named parameter was invalid, plus the call stack showing
> where it was called in context.  If throwing an error is not to your liking,
> you could also do:
>
>         local function foo(x)
>           if x < 1 or x > 10 then
>             return nil,debug.traceback('parameter "x" is out of range')
>           end
>
>           return x + 3
>         end
>
> to mimic the common Lua idiom of returning nil plus an error message.
>
>   -spc
Reply | Threaded
Open this post in threaded view
|

Re: How to acquire the name of the variables passes to the self-defined C function which has been successfully set by lua_register()?

Sean Conner
It was thus said that the Great 孙世龙 sunshilong once stated:
> >What's wrong with error()?
> Sorry for my poor English.

  And you missed the point of my first message.  What's the variable name in
the following call?

        self_def_func(150,"test")

There are no variables being passed in.  They are literal values.  Or this
example:

        self_def_func((150 - 32) / 1.8,"test")

Again no variable, but an expression.

  The information you want doesn't exist.  You are assuming a particular way
of passing in a paramter to a function that isn't always the case.  Again,
what's wrong with error()?

int self_def_func(lua_State *L)
{
  int argc = lua_gettop(L);
  int type = lua_type(L,1);
 
  if (type != LUA_TNUMBER)
  {
    luaL_traceback(L,L,"paramter 'temperature' not number",0);
    lua_error(L);
  }
  else
  {
    double val = lua_tonumber(L,1);
    if (var > 100)
    {
      luaL_traceback(L,L,"paramter 'temperature' out of range",0);
      lua_error(L);
    }
  }
}

  You get a stack traceback to the calling location where the problem most
likely is.  

  Again, I repeat, the information you want does not, and probably cannot
exist.

  -spc
Reply | Threaded
Open this post in threaded view
|

Re: How to acquire the name of the variables passes to the self-defined C function which has been successfully set by lua_register()?

Sudipto Mallick
Lua tells us where the error occured: the file name and line number.
How can the line itself be printed in the stack traceback? Why does
not Lua do that already?

--Sudipto Mallick
Reply | Threaded
Open this post in threaded view
|

Re: How to acquire the name of the variables passes to the self-defined C function which has been successfully set by lua_register()?

Sean Conner
It was thus said that the Great Sudipto Mallick once stated:
> Lua tells us where the error occured: the file name and line number.
> How can the line itself be printed in the stack traceback? Why does
> not Lua do that already?

  Because the "file" might not exist.

  At work, I compile a Lua application, plus all the modules (both in C and
Lua) into a single executable.  The modules written in Lua are compressed
(using zlib) and stored into the exectuable as blobs of data that the custom
loader knows how to uncompress and hand back to Lua.  There is no "file" to
speak of, but it can still report useful information:

        [string "org.conman.example"]:32: attempt to call a nil value (global 'print')

  -spc
Reply | Threaded
Open this post in threaded view
|

Re: How to acquire the name of the variables passes to the self-defined C function which has been successfully set by lua_register()?

Sudipto Mallick
Sunshilong, If you want something like named parameters (aka named
arguments or keyword arguments), you can emulate that in Lua using
tables:
    foo{a = 10} -- error: parameter 'b' is required
    foo{a = 10, b = "meh"} -- error: parameter 'b' must be a number
    foo{a = 10, b = 123} -- error: parameter 'b' must be greater than
0 and less than 100
    foo{a = 10, b = 20} -- ok
That table is passed as the first argument into 'foo'. Not exactly
what you wanted, but I think you wanted something like this.
---

Sean Conner, so when the source code is available [from file or
string], it is possible to print the line or the most relevant part of
that line. We can't have line number information for C code from lua,
so there is the '[?]'. But when the source code *is* available, I
think printing the lines itself along with the error is helpful.
--Sudipto Mallick
Reply | Threaded
Open this post in threaded view
|

Re: How to acquire the name of the variables passes to the self-defined C function which has been successfully set by lua_register()?

孙世龙 sunshilong
>Sunshilong, If you want something like named parameters (aka named
>arguments or keyword arguments), you can emulate that in Lua using
>tables:
>   foo{a = 10} -- error: parameter 'b' is required
>   foo{a = 10, b = "meh"} -- error: parameter 'b' must be a number
>    foo{a = 10, b = 123} -- error: parameter 'b' must be greater than
> 0 and less than 100
>    foo{a = 10, b = 20} -- ok
>That table is passed as the first argument into 'foo'. Not exactly
>what you wanted, but I think you wanted something like this.

It's a solution. But, maybe, not a good one.

You see, the parameters passed to the C function are tables already,
e.g:

carState =  {};
personState = {};
roadState ={};

calc(carState, personState, roadState)

It's not a good idea to replace the aforementioned code snippet with
another one like this:
calc({`carState`=carState, 'personState'=personState, `roadSate`=roadState).

The aforementioned tables(i.e carState and etc) are  already complicated.
It's not a good idea to put these tables into another table.

One more question, is there a clerical error in your last email?
I think it should be foo({a = 10, b= 129}) instead of foo{a = 10, b = "meh"}.

Best regards
Sunshilong
Reply | Threaded
Open this post in threaded view
|

Re: How to acquire the name of the variables passes to the self-defined C function which has been successfully set by lua_register()?

suote127
>One more question, is there a clerical error in >your last email? 
No,there is not.
>I think it should be foo({a = 10, b= 129}) >instead of foo{a = 10, b = "meh"}. 
When a table constructor is the only argument passed to a function,() is optional.
Reply | Threaded
Open this post in threaded view
|

Re: How to acquire the name of the variables passes to the self-defined C function which has been successfully set by lua_register()?

Sudipto Mallick
In reply to this post by 孙世龙 sunshilong
> It's a solution. But, maybe, not a good one.
>
> You see, the parameters passed to the C function are tables already,
> e.g:
>
> carState =  {};
> personState = {};
> roadState ={};
>
> calc(carState, personState, roadState)
You see, we can not read your mind. But from the example you have
provided, I think the following can be done:
        state = { car = {}, person = {}, road = {} }
        -- ... initialize state ...
        calc(state)

> It's not a good idea to replace the aforementioned code snippet with
> another one like this:
> calc({`carState`=carState, 'personState'=personState,
> `roadSate`=roadState).
>
> The aforementioned tables(i.e carState and etc) are  already complicated.
> It's not a good idea to put these tables into another table.
That is up to you. When you are writing code, you decide how to
structure your code and data.
> One more question, is there a clerical error in your last email?
> I think it should be foo({a = 10, b= 129}) instead of foo{a = 10, b =
> "meh"}.
In lua, when the first and only argument to a function is a table
constructor or a string literal, you can drop the parenthesis.

Question to others: when it was introduced in lua?
--Sudipto Mallick