Lua callbacks with meta data - c++

I want to setup a couple of functions in Lua for scripters but when those functions are invoked, I'd like them to actually invoke a single function with a parameter that I define. This might look like:
Lua:
foo1()
foo2()
C++:
int myFunction( lua_State * context )
{
int numArgs = lua_gettop( context );
int topOfStack = -3;
bool lightUserDataFlag = lua_islightuserdata( context, topOfStack );
if( lightUserDataFlag )
{
}
}
}
So I am a little confused on the setup. I am trying to register the callback with a param. This is what I have so far and there is something that is not saving the param with the function registration; it seems to only save the last param I add.
void setupCallback()
{
lua_register( context, "foo1", Callback);
lua_pushlightuserdata( context, &value[0] );
lua_register( context, "foo2", Callback);
lua_pushlightuserdata( context, &value[1] );
}
When lua invokes my callback, I always see the value[1], never the value[0]. I played with the notion of registering the callback and then adding a table, but I'm not sure that this will get me any further.
As to the why: I am trying to abstract function names to make writing code for our lua programmers easier, but those simply need to translate into the same parameterized function. Think of it add changing settings by passing a single param, but naming that differently.
Thoughts?

You likely want to attach those context values as upvalues of your function. Take a look at lua_pushcclosure().
Incorporating Mickey Kawick's comment:
int Callback (lua_State *context)
{
int val= lua_tointeger( context, lua_upvalueindex(1) );
cout << val << endl;
...
}
void setup()
{
lua_pushnumber( context, 3 );
lua_pushcclosure( context, Callback, 1 );
lua_setglobal( context, "foo1" );
lua_pushnumber( context, 42 );
lua_pushcclosure( context, Callback, 1 );
lua_setglobal( context, "foo2" );
}

Related

How to use c++14 variadic templates with sdbus callbacks

The sd-bus requires one to callback functions when defining d-bus methods. As i am doing C++14, i would like to have those calls to a class object on_msg_method_here() functions. What i am trying to achieve is something like this (in pseudo c++):
int callback_dbus_method_foo( message* msg, void* userdata, ... )
{
MyClass* cls = (MyClass*)userdata;
Type0 var0;
if ( message_process( msg, signature[0], &var0 ) != 0 )
//.. error here
Type1 var1;
if ( message_process( msg, signature[1], &var1 ) != 0 )
//.. error here
//... and these continue from 0 to N
TypeN varN;
if ( message_process( msg, signature[N], &varN ) != 0 )
//.. error here
int dbus_ret = cls->on_msg_method_foo( var1, var2, ..., varN )
handle_dbus_ret( msg, dbus_ret // ... );
return 0;
}
int MyClass::register_callbacks( ... )
{
// Well really we have something really different, this is to demonstrate
// pass 'this' as userdata* to callback function
dbus_register_callback( "method_foo",
&callback_dbus_method_foo, this )
}
Now i know i can do this with C-macros, but how to do this properly with C++14 varidic macros?
As far as i understand, the trouble of calling certain class object certain method can be handled with std::bind (and pass that via userdata pointer), and the variable declaration and message_process can be done with variadic template peeling, but how to get those declared variables (var0, var1, .. on the pseudo code example) expanded properly to the call? In short, how to do this magic:
MyClass::register_callbacks()
{
Mystic fun_to_call = std::bind( &MyClass::on_dbus_method_foo, this );
dbus_register_callback( "method_foo",
super_magic_template<int,double,bool>, &fun_to_call );
}
There are a couple things I would do in order to get an elegant and generic solution.
We need a way to gather variables (var0, var1, ..., varN) and pass them to a function. For that, I would first have a wrapper that queries such variables given it's index i. I'm not sure what signature is in your exemple, but I'm sure you can work around this.
template <class T>
T get_var(message* msg, unsigned i) {
T var;
if ( message_process( msg, signature[i], &var ) != 0)
throw std::runtime_error("Oups"); // In this context, it's easier to deal with errors with exception.
return var;
}
We can then gather all variables by unpacking variadic template arguments, along with associated index_sequence used for indexing. Something like
template <class... Vars, class F>
void callback_wrapper(F& fcn, message* msg) {
callback_wrapper_impl(fcn, msg, std::make_index_sequence<sizeof...(Vars)>());
}
template <class... Vars, class F, size_t... i>
void callback_wrapper_impl(F& fcn, message* msg, std::index_sequence<i...>) {
fcn(get_var<Vars>(msg, i)...);
}
Another difficulty arises with using std::bind, which returns the function-like object fun_to_call. We can't pass that to dbus_register_callback as a function pointer, which does not carry any data, neither can we pass a pointer to it as userdata, because fun_to_call is a local variable, hence it's lifetime is too short.
Instead of relying only on a super_magic_template callback, I would do a wrapper around dbus_register_callback that offers a simpler interface, let's call it modern_dbus_register_callback. The most straightforward solution I see is to use dynamic storage duration at the cost of memory allocation and an extra level of indirection - this is similar to type erasure used in std::function. Note that you can optimize this if sizeof(fun_to_call) < sizeof(void*), by passing fun_to_call by value as userdata - this is small value optimization. I believe using lambdas with no capture can be useful, as they are convertibles to function pointers and avoid lots of template boilerplate. Some extra work might be required to handle errors while avoiding memory leaks.
template <class... Vars, class F>
void modern_dbus_register_callback(const char* name, F& fcn) {
std::unique_ptr<F> fcn_ptr = std::make_unique<F>(fcn);
dbus_register_callback(name, [](message* msg, void* userdata){
std::unique_ptr<F> fcn_ptr(static_cast<F*>(userdata));
callback_wrapper<Vars...>(*fcn_ptr, msg);
}, fcn_ptr.release());
}
This can then be used as
modern_dbus_register_callback<int,double,bool>("method_foo", fun_to_call);

Pass a callback function with a parameter to a function

I want to call the following function and pass it a function with a parameter. The purpose of that is that it should call the function with my specified parameter so I know what triggered the function (in that case a gpio pin on the Raspberry Pi).
int wiringPiISR( int pin, int edgeType, void (*function)( void ) );
Currently I have:
for ( int i = 0; i < myValues.size(); ++i )
{
int myValue = myValues[ i ];
wiringPiISR( myValue, INT_EDGE_RISING, &myCallback( myValue ) );
}
Though this is giving me the following error:
error: lvalue required as unary ‘&’ operand
Which I can't really understand as to my understanding, myValue is an lvalue or is it not?
Is it what I want do even possible? If so how?
The function wiringPiISR is from a library called wiringPi and I would like to avoid modifying it as much as possible.
You could combine the answers from imreal and Ryan Haining something like this.
std::function<void()> cbfunc;
void myCallback()
{
cbfunc();
}
void myWiringPiISR(int val, int mask, std::function<void()> callback)
{
cbfunc = callback;
wiringPiISR(val, mask, &myCallback);
}
... and then use it...
void myActualCallback(int v)
{
... do something...
}
myWiringPiISR(myValue, INT_EDGE_RISING, std::bind(myActualCallback, myValue));
No need to patch library, and you can use all the bind/function goodness. I'll leave you to find a way around the thread safety issues...
How does it work? Put simply 'std::bind' is binding together a function and it's parameters into a single std:function object which can then be 'called' from the myCallback function which acts as a shim around the callback that you pass. I'd given the callback function a confusing name before, but this edit has hopefully fixed that.
You can "vomit" the function. This doesn't require a user-defined mutable global variable and is thread-safe, unless you have a compiler that supports multiple threads but not per-thread exceptions which would be basically unusable.
myWiringPiISRWrapper(Value value, int edge, std::function<void()> func) {
try {
throw &func;
} catch(...) {
myWiringPiISR(value, edge, [] {
try {
throw;
} catch(std::function<void()>* func) {
(*func)();
}
});
}
}
It's disgusting and slow, but it's totally encapsulated which I think is a worthwhile upside. Note that this only works if the callback is never executed after the call to myWiringPiISR returns. In this case you can of course have a callback with whatever bound state you desire.
If myValue is something you can decide at compile time, you could set it statically and use an intermediate function to pass in.
void myCallbackHelper() {
static constexpr int myValue = 3;
myCallback(myValue);
}
wiringPiISR(myValue, INT_EDGE_RISING, &myCallbackHelper);
If you need to determine myValue at run time, you could still accomplish this, but not really thread-safely.
int& getMyValue() {
static int myValue;
return myValue;
}
void setMyValue(int i) {
getMyValue() = i;
}
void myCallbackHelper() {
myCallback(getMyValue());
}
Then set it and call
setMyValue(3);
wiringPiISR(myValue, INT_EDGE_RISING, &myCallbackHelper);
I looked up wiringPiISR and found that it is some sort of api call, so i am assuming you cannot change it.
Having said that, there is a reason most api-calls with a function-pointer-callback look sort of like this
void setCallback( void (*function)(void* data), void* userdata);
This allows people to cast their struct {blabla} data; to add some userdata, and when the function is called, it is passed along.
So basically, apart from hacking stuff with static variables, you can't pass any arguments.
You need to use std::function and std::bind.
Change your function signature to
int wiringPiISR (int pin, int edgeType, std::function<void()> func);
Inside you can call the callback simply using func()
And your call to:
int myValue = 3;
wiringPiISR(myValue, INT_EDGE_RISING, std::bind(myCallback, myValue));
What this does is create a std::function object (i.e. a callable) that wraps your function and keeps your desired value in its state.
This will only work on C++11 and newer.
If you have c++11, I suggest using std::function - it's quite a bit cleaner.
If not, your function signature is wrong. You want a callback with the type void(int) but your function takes a void()

LuaPlus manipulate table from C++

In this guide functions are created to add a monster to a table and to decrease the health of a monster from the table.
You can easily use the two functons like this from a lua script:
monster = objectMgr:CreateObject("HotMamma",5);
monster:Hurt( 1 ) --decrease health by 1
--or
objectMgr:CreateObject("HotMamma",5);
monster = objectMgr:GetObject(0)
monster:Hurt( 1 )
But how can I call these functions from the C++ side?
I mean the original ones: ObjectMgr::CreateObejct(), ObjectMgr::GetObjectByIndex() and Monster::Hurt()
I spend more than 8 hours on trying to figure this out! But nothing did work. :/
My best try was probably this:
// CreateObject modified to return pMonster and accept normal arguments
MonsterPtr monster = objectMgr.CreateObject(pState, "HotMamma", 5);
monster.Hurt( 1 );
This gives me the following error:
class "std::tr1::shared_ptr" has no member "Hurt"
From looking at the file Monster.hpp:
class Monster
{
// ...
public:
Monster( std::string& name, int health );
void Hurt( int damage );
void Push( LuaPlus::LuaState* pState );
int Index( LuaPlus::LuaState* pState );
int NewIndex( LuaPlus::LuaState* pState );
int Equals( LuaPlus::LuaState* pState );
};
typedef std::shared_ptr<Monster> MonsterPtr;
MonsterPtr is a C++ shared_ptr. So syntactically, you would have to call Monster's members with -> operator like:
// ...
monster->Hurt(1);
Edit: There seems to be some more setting up involved. The method signature:
int ObjectMgr::CreateObject( LuaPlus::LuaState* pState )
only accepts LuaState * as its only argument and it's not overloaded so the call above in your example isn't going to work. What you'll have to do is push the arguments onto the stack prior to the call. The setup and usage should look something like the following:
LuaObject _G = pState->GetGlobals();
LuaObject name, life;
name.AssignString(pState, "HotMamma");
life.AssignInteger(pState, 5);
_G["objectMgr"].Push();
name.Push();
life.Push();
MonsterPtr monster = objectMgr.CreateObject(pState);
monster->Hurt(1);

Allow managed code in hosted environment to call back unmanaged code

I have C++ code that hosts a clr in order to make use of Managed.dll, written in c#.
This .net has a method like the following that allows code to register for notification of events:
public void Register(IMyListener listener);
The interface looks something like this
public interface IMyListener
{
void Notify(string details);
}
I'd like to do stuff in the C++ part of the program, triggered by the events in the .net world. I would not even mind creating another managed dll for the sole purpose of making Managed.dll more C++-friendly, if that is necessary.
What are my options here? The only one I am sure I could implement is this:
Write another managed dll that listens for those events, queues them and lets the C++ code access the queue via polling
This would of course change from an 'interrupt' style to a 'polling' style with all its advantages and disadvantages and the need to provide for queuing. Can we do without polling? Could I somehow call managed code and provide it a function pointer into the C++ world as the argument?
Update
Thanks to stijn's answer and comments I hope I moved a bit in the right direction, but I guess the main problem still open is how to pass a fn pointer from unmanaged land into the clr hosted environment.
Say I have an "int fn(int)" type of function pointer that I want to pass to the managed world, here are the relevant parts:
Managed code (C++/CLI)
typedef int (__stdcall *native_fun)( int );
String^ MyListener::Register(native_fun & callback)
{
return "MyListener::Register(native_fun callback) called callback(9): " + callback(9);
}
Unmanaged code
typedef int (__stdcall *native_fun)( int );
extern "C" static int __stdcall NativeFun(int i)
{
wprintf(L"Callback arrived in native fun land: %d\n", i);
return i * 3;
}
void callCLR()
{
// Setup CLR hosting environment
...
// prepare call into CLR
variant_t vtEmpty;
variant_t vtRetValue;
variant_t vtFnPtrArg((native_fun) &NativeFun);
SAFEARRAY *psaMethodArgs = SafeArrayCreateVector(VT_VARIANT, 0, 1);
LONG index = 0;
SafeArrayPutElement(psaMethodArgs, &index, &vtFnPtrArg);
...
hr = spType->InvokeMember_3(bstrMethodName, static_cast<BindingFlags>(
BindingFlags_InvokeMethod | BindingFlags_Static | BindingFlags_Public),
NULL, vtEmpty, psaMethodArgs, &vtRetValue);
if (FAILED(hr))
wprintf(L"Failed to invoke function: 0x%08lx\n", hr);
The spType->InvokeMember_3 call will lead to a 0x80131512 result.
Something seems to be wrong with the way I pass the pointer to NativeFun over to the managed world, or how my functions are defined. When using a String^ param instead of the fn ptr, I can call the CLR function successfully.
You can write a seperate dll in C++/CLI and implement the interface there, and forward the logic to C++. From my experience with mixing managed/unmanaged I can say using an intermediate C++/CLI step is the way to go. No fiddling with DllImport and functions only, but a solid bridge between both worlds. It just takes some getting used to the syntax and marshalling, but once you have that it's practically effortless. If you need to hold C++ objects in the managed class, best way is to use something like clr_scoped_ptr.
Code would look like this:
//header
#using <Managed.dll>
//forward declare some native class
class NativeCppClass;
public ref class MyListener : public IMylIstener
{
public:
MyListener();
//note cli classes automatically implement IDisposable,
//which will call this destructor when disposed,
//so used it as a normal C++ destructor and do cleanup here
~MyListener();
virtual void Notify( String^ details );
private:
clr_scoped_ptr< NativeCppClass > impl;
}
//source
#include "Header.h"
#include <NativeCppClass.h>
//here's how I marshall strings both ways
namespace
{
inline String^ marshal( const std::string& i )
{
return gcnew String( i.data() );
}
inline std::string marshal( String^ i )
{
if( i == nullptr )
return std::string();
char* str2 = (char*) (void*) Marshal::StringToHGlobalAnsi( i );
std::string sRet( str2 );
Marshal::FreeHGlobal( IntPtr( str2 ) );
return sRet;
}
}
MyListener::MyListener() :
impl( new NativeCppClass() )
{
}
MyListener::~MyListener()
{
}
void MyListener::Notify( String^ details )
{
//handle event here
impl->SomeCppFunctionTakingStdString( marshal( details ) );
}
update
Here's a simple solution to call callbacks in C++ from the managed world:
pubic ref class CallbackWrapper
{
public:
typedef int (*native_fun)( int );
CallbackWrapper( native_fun fun ) : fun( fun ) {}
void Call() { fun(); }
CallbackWrapper^ Create( ... ) { return gcnew CallbackWrapper( ... ); }
private:
native_fun fun;
}
you can also wrap this in an Action if you want.
Another way is using GetDelegateForFunctionPointer, for example as in this SO question
If someone still needs a better way for this , you can simply pass c++ function to CLR using intptr_t in variant and long in managed , then use Marshall and delegate to invoke your native function , super easy and works like charm.
if you need a code snippet , let me know.

Get the lua command when a c function is called

Supposed I register many different function names in Lua to the same function in C. Now, everytime my C function is called, is there a way to determine which function name was invoked?
for example:
int runCommand(lua_State *lua)
{
const char *name = // getFunctionName(lua) ? how would I do this part
for(int i = 0; i < functions.size; i++)
if(functions[i].name == name)
functions[i].Call()
}
int main()
{
...
lua_register(lua, "delay", runCommand);
lua_register(lua, "execute", runCommand);
lua_register(lua, "loadPlugin", runCommand);
lua_register(lua, "loadModule", runCommand);
lua_register(lua, "delay", runCommand);
}
So, how do I get the name of what ever function called it?
Another way to attack your question is by using upvalues. Basically, you register the C functions with the function below instead of lua_register:
void my_lua_register(lua_State *L, const char *name, lua_CFunction f)
{
lua_pushstring(L, name);
lua_pushcclosure(L, f, 1);
lua_setglobal(L, name);
}
Then, getFunctionName is straight forward
const char* getFunctionName(lua_State* L)
{
return lua_tostring(L, lua_upvalueindex(1));
}
That said, what you trying to do seems fishy - what are you trying to achieve? The runCommand function posted in the question looks like a horribly inefficient way to do something that Lua does for you anyway.
You can use lua_getinfo : http://pgl.yoyo.org/luai/i/lua_getinfo
This might work:
const char* lua_getcurrentfunction(lua_State* L) {
lua_Debug ar;
lua_getstack(L, 1, &ar);
lua_getinfo(L, "f", &ar);
return ar.name;
}
There is one caveat:
name: a reasonable name for the given function. Because functions in Lua are first-class values, they do not have a fixed name: some functions may be the value of multiple global variables, while others may be stored only in a table field. The lua_getinfo function checks how the function was called to find a suitable name. If it cannot find a name, then name is set to NULL.
An alternative solution would be to register a metatable for the Lua environment table that implements the __index metamethod for dispatching these functions calls.
Unfortunately, that's not possible - among other things, because functions in Lua don't actually have to have a name at all. (Consider: (loadstring("a=1"))() is executing a nameless function returned from loadstring.)
If you're willing to slurp up all unknown function executions, you may be able to play games with setmetatable and currying:
-- This function would not be in lua in your example,
-- you'd be doing lua_register( lua, "runCommandNamed", runCommandNamed )
-- and writing a runCommandNamed in C.
function runCommandNamed( cmd, ... )
print( "running command", cmd, "with arguments", ... )
end
-- The rest would be somewhere in lua-land:
local utilMetaTable = {
__index = function ( t, key )
return function( ... ) -- mmm, curry
runCommandNamed( key, ... )
end
end
}
_util = {}
setmetatable( _util, utilMetaTable )
-- prints "running command CommandOne with arguments arg1 arg2 arg3"
_util.CommandOne( "arg1", "arg2", "arg3" )
-- prints "running command CommandTwo with arguments argA argB"
_util.CommandTwo( "argA", "argB" )
In this example, I've only slurped up unknown executions under _util rather than in the global table.