I need to call a Lua function from C and as long the function is global I can find it in the global table, but if it is declared local, how can I push the address on the stack to call it?
function MyGlobal()
print("Global")
end
local function MyLocalGlobal()
print("Local")
end
Calling MyGlobal() from C isn't a problem it works fine. I lookup the function in the global table.
But how do I call MyLocalGlobal() from C? It isn't in the global table, but where is it and how can I push the address?
I'm using Lua 5.3.4.
The MyLocalGlobal() function isn't really global. It's local to the anonymous function that represents the whole chunk of loaded code.
What is really happening when you call lua_load/lua_loadstring:
return function(...) -- implicit functionality outside of code to be loaded
-- your file starts here --
function MyGlobal()
print("Global")
end
local function MyLocalGlobal()
print("Local")
end
-- file ends here --
end -- implicit functionality outside of code to be loaded
You can get MyLocalGlobal later either with debugging facilities (by means of 'debug' library), or you should explicitly return required interface at the end of that source file, and grab/read the interface on native side right after you've loaded/executed the chunk.
Related
Example in C, Static variables have a property of preserving their value even after they are out of their scope. Hence, static variables preserve their previous value in their previous scope and are not initialized again in the new scope.
How can I achieve the same functionality in Ada language where the variable is ensured to live until the end of the progran but its scope should be limited to the function hence also ensuring data coupling?
Variables declared directly in package specifications and bodies retain their state as long as the program is running.
You can't keep variables local to a subprogram as such, but you can declare a single subprogram inside a package, and declare the persistent variables in the body of the package.
In c, when a variable is defined static within a function, the value of the variable is retained all the time. So probably, it's stored in the bss or data section.
However, in Eclipse CDT debugging, when trying to inspect this variable, typing the variable name in the expression pane only display the variable when the stack frame is in the function, like local variable.
Is it a bug in eclipse ?
Edit:
In IAR Embedded workbench, static variables in functions can be watched outside the function in debugging, so it's possible.
While the variable is, in fact, stored in the heap... it remains that the scope of the variable is local to the function. It's value has no meaning outside of that function and it should never change when outside of the function... unless you're passing pointers to it around, in which case you can view it in any function that has access to that pointer.
So... no... it's not a bug.
You need to qualify the static variable with the function in order to determine the scope, e.g. foo::myvar if myvar is defined in function foo.
I am trying to write a program where I have to call some functions through a (shared) library (its source is available). The C code for the library has several global variables, and many functions change the values of these global variables. What I have to do in my program requires that each function call that I make gets to work with a fresh set of variables.
For example, let this function be a part of the library:
int x = 1;
int foo()
{
int a = 0;
//do somethings to 'a'
//...
x++;
return a;
}
Now every time I invoke foo() from my program, the value of x gets update from 1 to 2 then 3 then 4 and so on... I am try to construct a program so that every time foo() is invoked, it sees x = 1.
I am sorry to say that my knowledge of how C/linux treat these variable spaces is insufficient, so this question may seem vague. The above is just a small example; in reality, there are so many variables that is practically impossible to reset their values manually.
What may be the best way to compile that library and/or use it my program so as to refresh the variables?
(On a side note, what I am also trying to do is to parallelize calls to foo(), but because of the shared variables, I cannot do that.)
EDIT:
When working on some web dev projects, I used to encapsulate some code in webservices and then invoke those services from the main program. Does a similar framework exist in C/Linux? Please note that functions are returning data.
You have discovered one of the main reasons that global variables (or global state in general) are a really bad idea.
Since you have access to the source, I would suggest investing some time to refactor the source code.
You can achieve the ability to parallelize calls to foo with the following strategy:
Gather up all of the global variables into a single struct. Call it something like Context.
Change each function that acts on a global variable to take a pointer to a Context, and change the function to update the variables in the Context instead of updating global variables.
Now each thread that wants to use the library can create a new Context and pass that into foo and related functions.
If it's not feasible to make such a change to the source code, you can use more than one CPU core by starting child processes. Each child process has it's own memory space. That option is not nearly as efficient as using multiple threads.
I have no answer in details. But you can try one of the following:
unload and load library
try to clear library's .bss and fill .data section with values from the library (ref dl_iterate_phdr() call).
I'm currently building a lua event system (in lua), however I want to be able to fire events from C too, I was wanting to bind a C function to a lua function, such that the C function could fire events in lua, I was planning to use the:
lua_register
function; however I can't seem to find a way to bind my lua function like this, it would seem I'm in need of a lua function that does the same, but from the lua side, I was thinking about making some hack, by binding a C function into lua, that simply calls 'lua_register', but this seems a bit unsafe to me.
So what should I do instead?
I'm not fully sure I understand what you've asked for. So allow me to explain what I think your question is.
You have some Lua code. In that Lua code, you have a system. This system is, at some point, given one or more events. For each event that it is given, it calls some function or functions that were registered to be called when that particular event was given.
So, this system has two basic functions:
EventSystem:RegisterEventHandler(EventName, Func);
EventSystem:FireEvent(EventName, ...);
The RegisterEventHandler method will associate the given Func with the given EventName, such that when FireEvent is called later, Func will be called if the EventName given to FireEvent is the same one Func was registered with.
Now you want to have C code be able to register C functions as event handlers. So it's time to talk about registering C functions in Lua.
The C API call lua_register is actually a macro. It creates a C function on the Lua stack, then puts it in the global table, using the string index given to lua_register. These are two separate operations; lua_register is just a convenience function that makes them the same.
What you want is to call RegisterEventHandler from C code, passing the C function as the third parameter (remember: the first parameter is self, because I called RegisterEventHandler with : instead of .. If you're using a global event system rather than an object oriented one, you only have two parameters). This requires two things:
You have to know how to call Lua functions from C code.
You have to know how to pass a C function to Lua code.
Step 1: It's all done via the Lua stack (I'll assume you know how that works. If not, I have a pretty substantial answer that explains most everything you might want to know about it).
The first thing you need to do is get the function you want to call onto the stack. To do that, you need to get an event system object (again, if your event system is global, just get the global table) and push it onto the stack. How you do that depends on where your event system objects are stored. Presumably you can get them through the global table.
Once you have the event system on the stack, you just index it with the "RegisterEventHandler" string, which will return to you the Lua function we need.
Next, we push our parameters onto the stack, from first to last. The first parameter is the event system object; it's probably still on the stack, so we can copy it. The second is the event name, and that's easy to push. The third is the C function. Which leads us to:
Step 2: lua_register is not going to get the job done. It's too heavy handed; it puts the C function in the global table. We need it on the stack. So we must use a lower level function: lua_pushcclosure. Or lua_pushcfunction, if you don't need upvalues.
These functions take a C function, wrap it up in Lua, and push it onto the Lua stack.
Now that the 3 parameters are on the stack, we can call the event registration function with a call to lua_pcall. Or your favorite Lua function calling function; however you wish to do it. Lua will consume the 3 parameters and the function itself, so that they are no longer on the stack.
And since the event registration function probably doesn't return values, the stack will be where it was right before we got the function onto the stack (but not before we started, depending on how much cleanup was done while getting the function).
After this, your C function will be registered with the event handler for that event name.
If I have some lua code like this:
doSomething(function()
print("Hello!")
end)
How can I make it that, using the C API, I create C Lua function for doSomething that can then save the function passed to it to be executed a later date?
It's just a normal entry on the stack. Check it with lua_isfunction() then use luaL_ref() to generate a reference (so that the garbage collector doesn't steal it), and then maybe lua_topointer() to store a pointer to this object, depends what you want to do with it.
When you're finished it's just a luaL_unref().