Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How do you pass functions as delegates? #491

Closed
vlOd2 opened this issue Jun 6, 2023 · 10 comments
Closed

How do you pass functions as delegates? #491

vlOd2 opened this issue Jun 6, 2023 · 10 comments

Comments

@vlOd2
Copy link

vlOd2 commented Jun 6, 2023

How do you pass functions as delegates to C# methods/classes that expect a delegate?
For example, there is the winforms method for controlls called Invoke that expects a Delegate
In C#, you'd normally pass your function as an instance of Action by doing Action(My Function)

But how can you do this in Lua? I tried just Invoke(My Function) but that gives Invalid arguments to method: Control.Invoke and I also tried creating an Action by doing Invoke(Action(My Function)) but that gives System.Action does not contain constructor(.ctor) argument match

Also My Function is just a placeholder

@viniciusjarina
Copy link
Member

If is an event you can use Add to subscribe to it
like here https://github.com/NLua/NLua/blob/main/extras/examples/form_alt.lua#L27

@vlOd2 vlOd2 changed the title How do you pass functions as delegates? How do you pass functions as delegates Jun 6, 2023
@vlOd2 vlOd2 changed the title How do you pass functions as delegates How do you pass functions as delegates? Jun 6, 2023
@vlOd2
Copy link
Author

vlOd2 commented Jun 6, 2023

@viniciusjarina That is not the solution, I do know that events can be subscribed to with Add and unsubscribed from by passing the EventHandler returned from add to Remove, I am asking how to create delegate Action and pass that to the Invoke method on controls?

@vlOd2
Copy link
Author

vlOd2 commented Jun 6, 2023

In the meantime, I wrote myself a quick workaround, but I wonder if there is any intended way to do what I asked

@vlOd2
Copy link
Author

vlOd2 commented Jun 6, 2023

My workaround for those interested:

// You should probably put this in a different table rather than global, like how I did in the code where I use this, but this works too
Script["ControlInvoke"] = new Action<Control, Action>((Control control, Action action) => control.Invoke(action));

@viniciusjarina
Copy link
Member

viniciusjarina commented Jun 6, 2023 via email

@vlOd2
Copy link
Author

vlOd2 commented Jun 9, 2023

I tried it, it just throws the exception I said in the issue

@viniciusjarina
Copy link
Member

viniciusjarina commented Jun 9, 2023 via email

@vlOd2
Copy link
Author

vlOd2 commented Jun 10, 2023

I am trying to pass a method to a Delegate parameter, for example System.Windows.Forms.Control.Invoke() takes a delegate, and I tried passing the method directly (Invoke(MyFunc)) but it threw Invalid arguments to method: Control.Invoke and I also tried wrapping it in an Action (Invoke(Action(MyFunc))) as you'd normally do in C#, but that threw System.Action does not contain constructor(.ctor) argument match

@vlOd2
Copy link
Author

vlOd2 commented Jun 10, 2023

Here is a test case, the method MyMethodThatTakesADelegate has the arguments as one of the overloads of System.Windows.Forms.Control.Invoke

class Program
{
    static void Main(string[] args)
    {
        MyMethodThatTakesADelegate(new Action(() => 
        {
            Console.WriteLine("Hello from C#!");
        }));

        Lua lua = new Lua();
        lua.LoadCLRPackage();
        lua["MyMethodThatTakesADelegate"] = (Action<Action>)MyMethodThatTakesADelegate;

        try
        {
            /*
             * MyMethodThatTakesADelegate(function() 
             *      print("Hello, world")
             * end)
            */
            lua.DoString("MyMethodThatTakesADelegate(function() print(\"Hello, world\")end)");
        }
        catch (Exception ex) { Console.Error.WriteLine($"First test case failed: {ex}"); }

        try 
        {
            /*
             * import("System")
             * MyMethodThatTakesADelegate(Action(function() 
             *      print("Hello, world")
             * end))
            */
            lua.DoString("import(\"System\") MyMethodThatTakesADelegate(Action(function() print(\"Hello, world\") end))");
        }
        catch (Exception ex) { Console.Error.WriteLine($"Second test case failed: {ex}"); }
        Console.ReadLine();
    }

    public static void MyMethodThatTakesADelegate(Delegate myDelegate) 
    {
        myDelegate.DynamicInvoke();
    }
}

@vlOd2
Copy link
Author

vlOd2 commented Jun 10, 2023

Output of test case using the latest version of NLua on .NET 4.7.2 (also on .NET 4.6 where I first discovered this bug/lack of support)

Hello from C#!
First test case failed: NLua.Exceptions.LuaScriptException: [string "chunk"]:1: Cannot invoke delegate (invalid arguments for  MyMethodThatTakesADelegate)
Second test case failed: NLua.Exceptions.LuaScriptException: [string "chunk"]:1: System.Action does not contain constructor(.ctor) argument match

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants