Lua C API: Handling and storing additional arguments - c++

CreateEntity is a C function I bound to Lua in my project. It takes an entity class name string as first argument, and any number of additional arguments which should get passed to the constructor of the chosen entity.
For example, if CreateEntity was a normal Lua function I could do it this way:
function CreateEntity( class, ... )
-- (choose a constructor function based on class)
args = {...}
-- (store args somewhere for whatever reason)
TheConstructor( ... )
end
But how can I do this with a C Lua function?

The C function lua_gettop will return how many parameters were passed to your C function. You must either read these all from the stack and store them in a C data structure, or place them in the Lua registry (see Registry and luaL_ref) and store references to them for later use. The example program below uses the registry approach.
#include <lauxlib.h>
#include <lua.h>
#include <lualib.h>
#include <stdio.h>
#include <stdlib.h>
/* this function prints the name and extra variables as a demonstration */
static void
TheConstructor(lua_State *L, const char *name, int *registry, int n)
{
int i;
puts(name);
for (i = 0; i < n; ++i) {
lua_rawgeti(L, LUA_REGISTRYINDEX, registry[i]);
puts(lua_tostring(L, -1));
}
free(registry);
}
static int
CreateEntity(lua_State *L)
{
const char *NAME = luaL_checkstring(L, 1);
int *registry;
int i, n;
/* remove the name parameter from the stack */
lua_remove(L, 1);
/* check how many arguments are left */
n = lua_gettop(L);
/* create an array of registry entries */
registry = calloc(n, sizeof (int));
for (i = n; i > 0; --i)
registry[i-1] = luaL_ref(L, LUA_REGISTRYINDEX);
TheContructor(L, NAME, registry, n);
return 0;
}
int
main(int argc, char **argv[])
{
const char TEST_CHUNK[] =
"CreateEntity('foo', 1, 2, 3, 4, 5, 6, 7, 8, 9, 10)";
lua_State *L;
L = luaL_newstate();
lua_register(L, "CreateEntity", CreateEntity);
luaL_dostring(L, TEST_CHUNK);
lua_close(L);
return EXIT_SUCCESS;
}

args = {...}
-- (store args somewhere for whatever reason)
The arguments of the call are on the Lua stack and you can do with them as you please: put them in a structure of your own (std::vector<boost::any> or something like that) or store individual arguments in the Lua registry or create a Lua table with the arguments and store that in the registry instead. What suits you better?
TheConstructor( ... )
I'm fairly convinced this part is not possible in C++ the way it is in Lua. C++ requires the number of parameters you pass to a function to be known at compile time.
It's a major inconvenience to try and do those things in C++. Maybe be betters solution will come if you tell us why do you want your CreateEntity function to be on the C++ side instead of Lua.

Related

how to write a function that links other functions in C [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
Lets say I have functions A, B, & C.
I would like to write a function which looks like:
Linker(A,B,C,{{0,1,0},{0,0,1},{0,0,0}});
where the arrays correspond to which element in the first list will be called. In other words, when A finishes, it starts the second element B, when B finishes it calls the third element C, when C finishes nothing is called.
Linker would then unroll into
generic preprocessing
run A
generic postprocessing
generic preprocessing
run B
generic postprocessing
generic preprocessing
run C
generic postprocessing
The idea being that this would make it easier to link functions together, and would save me some time in writing the pre and postprocessing steps. Also organization, error-proofing, understandability, etc... Is this Idea possible in C? would I need to use C++? how do I begin implementing an idea like this?
I am using stm32ide as my compiler as this code will run on an embedded device.
You could do this by setting up some "processing" class that stores pointers to your functions and the links you want to establish between them:
class processor {
private:
std::vector<void (*)()> funcs;
std::vector<std::pair<int, int>> links;
public:
void add_func(void (*func)()) { funcs.push_back(func); }
void link(int from, int to) { links.push_back({from, to}); }
void call(int indx) {
// Make the call
funcs.at(indx)();
// Call any links
for(auto it : links) {
if(it.first == indx) { call(it.second); }
}
}
};
Then to use it, you just need to add your functions and links, and then call call():
int main() {
processor p;
p.add_func(A);
p.add_func(B);
p.add_func(C);
p.link(0, 1); // A -> B
p.link(1, 2); // B -> C
p.call(0); // Call A
return 0;
}
See it in action here: https://ideone.com/M1Qj6f
If I understand you correctly you want to pass a function as a parameter to another function.
For c++ you can use function pointers.
#include <iostream>
void helloWorld()
{
std::cout << "Hello World" << std::endl;
}
int main()
{
helloWorld();
# Here we get the memory adress of the function helloWorld.
auto secondHelloWorld = &helloWorld;
# Here, an implicit converstion is going on.
auto thridHelloWorld = helloWorld;
secondHelloWorld();
thirdHelloWorld();
std::cin.get();
}
If you want to be more explicit with the types, you can write
#include <iostream>
void helloWorld()
{
std::cout << "Hello World" << std::endl;
}
int main()
{
helloWorld();
void(*secondHelloWorld)() = helloWorld;
void(*thridHelloWorld)() = helloWorld;
secondHelloWorld();
thirdHelloWorld();
std::cin.get();
}
I can not help you with how you should precisly implement this. I would need to know you requirements.
HTH
Your question should be clarified. If I understand well, you want to wrap a function, as done in a context manager. You should precise what is the signature of your functions A, B, C and how must be used {{0,1,0},{0,0,1},{0,0,0}}.
So to keep it simple, I'll assume that these three functions takes no parameter and do not return anything.
#include <stdio.h>
void context_manager(
void (*f)(),
void (*enter)(),
void (*exit)()
) {
enter();
f();
exit();
}
void my_enter() { printf("generic preprocessing\n"); }
void my_exit() { printf("generic postprocessing\n\n"); }
void a() { printf("run A\n"); }
void b() { printf("run B\n"); }
void c() { printf("run C\n"); }
void linker(void **fs, unsigned n) {
for (unsigned i = 0; i < n; i++) {
context_manager(fs[i], my_enter, my_exit);
}
}
int main() {
void * fs[] = {a, b, c};
linker(fs, sizeof(fs) / sizeof(void *));
return 0;
}
Result:
generic preprocessing
run A
generic postprocessing
generic preprocessing
run B
generic postprocessing
generic preprocessing
run C
generic postprocessing
You can obviously adapt the signature of f and linker to pass some parameter(s).
The hard part is that: Linker(A,B,C,{{0,1,0},{0,0,1},{0,0,0}}); cannot be written in C. The language lacks:
automatic processing or variable numbers of parameters for a function: you have to give a hint for the number and the function will have to guess the type
litteral multi-dimensional arrays do not exist in the language.
Said differently, I can imagine how to write something able to accept that syntax (apart from the semicolon) in Python, but not in C. Building a thing able to process a bunch of functions and chain them according to something is not a problem and can be done in C. But I cannot guess what the something should be, and how you intend to pass the functions and the something to the thing while respecting C syntax.
Assuming I understand what you're going for, and assuming all the functions have the same return type and argument lists, you could set up an array of function pointers and an array of integers to indicate which function to execute out of that list:
void A(void) { puts( "In A" ); }
void B(void) { puts( "In B" ); }
void C(void) { puts( "In C" ); }
/**
* Call each of the functions in f based on the values in seq;
* each seq[i] is treated as an index into f.
*
* A negative value in seq[i] indicates the end of the sequence.
*
* Inputs:
* f - list of functions we want to execute
* seq - specifies the order in which the functions are to be executed
*/
void Linker( void (*f[])(void), int *seq )
{
for ( int i = 0; seq[i] >= 0; i++ )
{
f[seq[i]]();
}
}
int main( void )
{
/**
* Use compound literals to set up each array.
*/
Linker( (void (*[])(void)) {A, B, C}, (int []) {0, 1, 2, 2, 1, 2, 0, 0, 0, -1} );
}
Output:
In A
In B
In C
In C
In B
In C
In A
In A
In A
If the functions have different return types, or if they have the same return types but take different parameter lists (or even the same parameter lists with different values), then this will need to be fleshed out a bit. You may need to create a C equivalent of a "functor" (basically a struct type that abstracts away the function return type and other details). But it should give you some ideas.

Make certain local variables available to LLVM pass

I have the following situation.
I need to insert certain CallInst in my code.
The prototype of my function is
void __llvmFooBar(int data, int loc);
The parameter loc is generated by the pass. I don't need any external data to generate that.
But, the parameter data is basically calculated by using some variable declared inside my C-code.
//test.c
int main()
{
int k = 0;
happyEnding(k);
}
void happyEnding(int k)
{
int __data = seed(time()) + k%2;
//callInst to be inserted here, it should be
//__llvmFooBar(__data, 23);
myAlgorithim();
}
//pass.cpp
......
std::vector<Value *> args(2);
args[0] = ??? //need help here
args[1] = ConstantInt::get(IntegerTy, getLoc());
m_builder->CreateCall(hook, args);
In generic sense, how to make all variable with specific naming convention(like starts with __) make available to llvm pass ?

Dynamic function calls at runtime (va_list)

There is a way in C to obtain a dynamic length argument list with va_list, as described here:
http://www.cprogramming.com/tutorial/c/lesson17.html
That quite simple, but most times in C++ not needed. I am currently building a top level wrapper class for encapsulating some Zend functionality.
Anyway, I do need to make a call to such a dynamic function like printf from a normal function dynamically.
I mean the reverse way of the example described above, here is waht I got so war, maybe this explains my idea a little better:
void ZendParams::setRequired( int &Var )
{
// save every var pointer to a stack
// and save the type with it. (if needed, does not seems to be)
// after call to ZendParams::fetch()
// the values are stored in the passed variables
this->_params.push_back( (void*) &Var );
this->_paramStr.append( 'i' );
}
size_t ZendParams::fetch()
{
if ( zend_parse_parameters(
ZEND_NUM_ARGS() TSRMLS_CC, ,
this->_paramStr.c_str(),
...
) !== FAILURE)
{
}
return 0;
}
So I want to make the call to zend_parse_parameters dynamically.
The base idea is to add pointer to vars in a list and pass them to the zend function (as reference) dynamically.
I thought there must be a way to do this with va_list , too.
But how?
To get it more simple, I am using this example:
list<int> myList;
myList.push_back(1);
myList.push_back(5);
myList.push_back(10);
myList.push_back(37);
myList.push_back(42);
double function avg( int num, ... )
va_list arguments;
int sum = 0;
va_start ( arguments, num );
for ( int x = 0; x < num; x++ )
{
sum += va_arg ( arguments, int );
}
va_end ( arguments );
return sum / num;
}
I want to call avg with all numbers I got in the list. I took the example function from the tutorial mentioned above, but it should show up what I mean in a very simple way.
However, I can not change the function called, as it is part of the zend framework.
Is there any way in C or C++ to do this?
My 2nd approach:
template <typename... Arguments>
size_t Zend::getMethodParams( string paramStr, Arguments... Args )
{
if ( zend_parse_parameters(
ZEND_NUM_ARGS() TSRMLS_CC, ,
paramStr.c_str(),
Args...
) == FAILURE)
{
return 0;
}
}
To be called like this (to get the defined 3 Parameters):
string My1stParam;
int My2ndParam;
int My3rdParam;
Zend::getMethodParams<string, int, int>( "sii", &My1stParam, &My2ndParam, &My3rdParam );
I think that should work, but there is one hard issue with that:
The zend_parse_parameters function returns 2 values for a string (c-style string!):
- a char pointer and
- the string length.
So I would either have to call it that way:
char* My1stParam_str;
int My1stParam_length
int My2ndParam;
int My3rdParam;
Zend::getMethodParams<string, int, int>( "sii", &My1stParam_str, &My1stParam_length, &My2ndParam, &My3rdParam );
string My1stParam;
My1stParam.assign(My1stParam_str, My1stParam_length);
Anyway, that was what I wanted to prevent.
Or I would have to modify the list of arguments passed to the zend_parse_parameters function to do these additional steps internally.
I am hoping to be able to call it at least in that way:
string My1stParam;
int My2ndParam;
int My3rdParam;
Zend::getMethodParams<string, int, int>( "sii", &My1stParam, &My2ndParam, &My3rdParam );
So say this clearly: The parameters are known at compile time, but the function call will be very different within all occurrences in the later sourcecode.
I found a way around this within the zend framework. I did indeed search for such a solution before, but it seems to be not very good documented ( n.m. already mentoined, that there is no zend internal way like a va_list taking function ).
But there is indeed one!
For everyone else stucking with this problem:
long arg;
zval ***args;
int i, argc = ZEND_NUM_ARGS( );
if (zend_parse_parameters(1 TSRMLS_CC, "l", &arg) == FAILURE) return;
array_init(return_value);
add_index_long(return_value, 0, arg);
if(argc>1) {
args = (zval ***)emalloc(argc * sizeof(zval **));
if(zend_get_parameters_array_ex(argc, args) == FAILURE) {
efree(args);
return;
}
for(i = 1; i < argc; i++) {
zval_add_ref(args[i]);
add_index_zval(return_value,i, *args[i]);
}
efree(args);
}
That is the solution ;)
This snippet, found on http://docstore.mik.ua/orelly/webprog/php/ch14_07.htm parses all parameters dynamically into the c representation of an PHP array.

Using LuaBridge with pointers to built-in types

Let's consider the following C function :
void returnMultipleValuesByPointer(int* ret0, int* ret1, int* ret2)
{
*ret0 = 0;
*ret1 = 1;
*ret2 = 2;
}
How to I expose it in Lua using LuaBridge ? All the documentation and examples illustrate complex cases where the pointed objects are classes but I can't find how to deal with such a simple case...
The trivial approach (ie luabridge::getGlobalNamespace(L).addFunction("test", &returnMultipleValuesByPointer)) compiles but does not understand the values are to be passed by address.
You can't do this directly. You have to write a wrapper method that will convert the parameters into return values. This requires writing such a method. For example, if these are pure return values (ie: they don't take parameters):
int lua_ReturnMultipleValuesByPointer(lua_State *L)
{
int ret0;
int ret1;
int ret2;
returnMultipleValuesByPointer(&ret0, &ret1, &ret2);
lua_pushinteger(L, ret0);
lua_pushinteger(L, ret1);
lua_pushinteger(L, ret2);
return 3;
}
You will need to register this with "addCFunction", since it's a standard Lua function.
If what you want to do is something like:
a=0
b=0
c=0
test(a,b,c)
-- NOW a is 0, b is 1, c is 2
I dont think it's possible. You should revert to a lua call like this:
a,b,c=test()
Now, test can be declared this way:
luabridge::getGlobalNamespace(L).addCFunction("test", &returnMultipleValues)
int returnMultipleValues (lua_State* L) {
push(L,0);
push(L,1);
push(L,2);
return 3;
}

Storing reference to lua function in C

I have a basic event handler implemented in C++. I also have an embedded Lua interpreter in my application that I need to interact with the Event Manager. The ultimate goal is to be able to have one event handler that will execute both c++ and Lua functions when an event is fired.
My problem is that I can't come up with a simple way to store references to the lua functions in my C++ code. I know how to execute Lua functions from c (using lua_getglobal and lua_pcall), but I would prefer to store a reference to the function itself, so that I can pass a Lua function directly to registerListener
Note It is acceptable to assume that userdata will be NULL for all Lua Listeners.
Here's my code:
EventManager.h
#include <string>
#include <map>
#include <vector>
using namespace std;
typedef void (*fptr)(const void* userdata, va_list args);
typedef pair<fptr, void*> Listener;
typedef map<string, vector<Listener> > CallbackMap;
class EventManager {
private:
friend ostream& operator<<(ostream& out, const EventManager& r);
CallbackMap callbacks;
static EventManager* emInstance;
EventManager() {
callbacks = CallbackMap();
}
~EventManager() {
}
public:
static EventManager* Instance();
bool RegisterEvent(string const& name);
void RegisterListener(string const &event_name, fptr callback,
void* userdata);
bool FireEvent(string name, ...);
};
inline ostream& operator<<(ostream& out, const EventManager& em) {
return out << "EventManager: " << em.callbacks.size() << " registered event"
<< (em.callbacks.size() == 1 ? "" : "s");
}
EventManager.cpp
#include <cstdarg>
#include <iostream>
#include <string>
#include "EventManager.h"
using namespace std;
EventManager* EventManager::emInstance = NULL;
EventManager* EventManager::Instance() {
if (!emInstance) {
emInstance = new EventManager;
}
return emInstance;
}
bool EventManager::RegisterEvent(string const& name) {
if (!callbacks.count(name)) {
callbacks[name] = vector<Listener>();
return true;
}
return false;
}
void EventManager::RegisterListener(string const &event_name, fptr callback,
void* userdata) {
RegisterEvent(event_name);
callbacks[event_name].push_back(Listener(callback, userdata));
}
bool EventManager::FireEvent(string name, ...) {
map<string, vector<Listener> >::iterator event_callbacks =
callbacks.find(name);
if (event_callbacks == callbacks.end()) {
return false;
}
for (vector<Listener>::iterator cb =
event_callbacks->second.begin();
cb != event_callbacks->second.end(); ++cb) {
va_list args;
va_start(args, NULL);
(*cb->first)(cb->second, args);
va_end(args);
}
return true;
}
luaw_eventmanager.h
#pragma once
#ifndef LUAW_EVENT_H
#define LUAW_EVENT_H
#include "EventManager.h"
extern "C" {
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
void luaw_eventmanager_push(lua_State* L, EventManager* em);
int luaopen_weventmanager(lua_State* L);
}
#endif
luaw_eventmanager.cpp
#include <assert.h>
#include <stdio.h>
#include <sstream>
#include <iostream>
#include "luaw_eventmanager.h"
using namespace std;
static int
luaw_eventmanager_registerevent(lua_State* L)
{
int nargs = lua_gettop(L);
if (nargs != 2) {
return 0;
}
stringstream ss;
ss << luaL_checkstring(L, 2);
EventManager::Instance()->RegisterEvent(ss.str());
return 1;
}
static int
luaw_eventmanager_registerlistener(lua_State* L)
{
return 1;
}
static int
luaw_eventmanager_fireevent(lua_State* L)
{
return 1;
}
static int
luaw_eventmanager_tostring(lua_State* L)
{
stringstream ss;
ss << *EventManager::Instance();
lua_pushstring(L, &ss.str()[0]);
return 1;
}
static const struct luaL_Reg luaw_eventmanager_m [] = {
{"registerEvent", luaw_eventmanager_registerevent},
{"registerListener", luaw_eventmanager_registerlistener},
{"fireEvent", luaw_eventmanager_fireevent},
{"__tostring", luaw_eventmanager_tostring},
{NULL, NULL}
};
void
luaw_eventmanager_push(lua_State* L, EventManager* em)
{
EventManager** emUserdata = (EventManager**)lua_newuserdata(L, sizeof(EventManager*));
*emUserdata = em;
luaL_getmetatable(L, "WEAVE.mEventManager");
lua_setmetatable(L, -2);
}
int
luaopen_weventmanager(lua_State* L)
{
luaL_newmetatable(L, "WEAVE.mEventManager");
lua_pushvalue(L, -1);
lua_setfield(L, -2, "__index");
luaL_register(L, NULL, luaw_eventmanager_m);
assert(!lua_isnil(L, -1));
return 1;
}
All Lua-owned objects are garbage-collected. This includes functions. Therefore, even if you could get a reference to a Lua function, Lua would still own it and thus it would be subject to the GC whenever Lua detects that it isn't being referenced anymore.
External code cannot own a Lua reference. But external code can store that reference in a place that Lua code cannot reach (and thus cannot break): the Lua registry.
The Lua registry is a Lua table (which is at stack pseudo-index LUA_REGISTRYINDEX, so it's accessible from the stack) which Lua code cannot (directly) access. As such, it is a safe place for you to store whatever you need. Since it is a Lua table, you can manipulate it like any other Lua table (adding values, keys, etc).
However, the registry is global, and if you use other C modules, it is entirely possible that they could start stomping on each other's stuff. So it's a good idea to pick a specific registry key for each of your modules and build a table within that registry key.
Step one: when initializing your C interface code, create a table and stick it in a known key in the registry table. Just an empty table.
When the Lua code passes you a Lua function to use as a callback, load that table from the special key and stick the Lua function there. Of course, to do that, you need to give each registered function a unique key (which you store as the Lua function's void* data), which you can later use to retrieve that function.
Lua has a simple mechanism for doing this: luaL_ref. This function will register the object on the top of the stack with the table it is given. This registration process is guaranteed to return unique integer keys for each registered object (as long as you don't manually modify the table behind the system's back). luaL_unref releases a reference, allo
Since the references are integer keys, you could just do a cast from int to void* and have that be the data. I would probably use an explicit object (mallocing an int), but you can store it however you like.
Step two: when a Lua function is registered, use luaL_ref to add it to the registry table created in step 1. Store the key returned by this function in the void* parameter for the registered function.
Step three: when that function needs to be called, use the integer key you stored in the void* parameter to access the registry table created in step 1. That will give you the function, which you can then call with the usual Lua methods.
Step four: when you are unregistering the Lua function, use luaL_unref to release the function (thus you avoid leaking Lua's memory). If you malloced memory to store the integer key, free it here.
I would suggest to store your functions into the registry and use the reference mechanism provided by the functions luaL_ref and luaL_unref.
These functions use an C int value to access the values. It is easy to store such an integer value in a C++ class member for example.
#Nicolas Bolas has provided nice instructions, but are too vague for newbies (including myself).
Through trial and error I have come up with working example:
Storage
lua_newtable(L); // create table for functions
int tab_idx = luaL_ref(L,LUA_REGISTRYINDEX); // store said table in pseudo-registry
lua_rawgeti(L,LUA_REGISTRYINDEX,tab_idx); // retrieve table for functions
lua_getglobal(L, "f"); // retrieve function named "f" to store
int t = luaL_ref(L,-2); // store a function in the function table
// table is two places up the current stack counter
lua_pop(L,1); // we are done with the function table, so pop it
Retrieval
lua_rawgeti(L,LUA_REGISTRYINDEX,tab_idx); // retrieve function table
lua_rawgeti(L,-1,t); // retreive function
//use function
//don't forget to pop returned value and function table from the stack
lua_pop(L,2);