digitalmars.D.learn - Calling arbitrary functions at runtime?
- Kevin Balbas (41/41) Dec 11 2016 I'm writing a system to register functions to be called at
- Adam D. Ruppe (14/16) Dec 11 2016 Write (or generate) a helper function that loops over the
- Kevin Balbas (4/20) Dec 11 2016 I see. I was planning on doing a wrapper-based approach to the
- ketmar (22/22) Dec 11 2016 import std.traits;
I'm writing a system to register functions to be called at runtime. With zero-argument functions, it works fine. However, I run into a problem with functions that take arguments. This is the relevant code I started with (zero-argument version): mixin template CommandSystemRegister(string s = __MODULE__) { void CommandSystemRegisterCommands() { foreach(name; __traits(allMembers, mixin(s))) { static if (hasUDA!(mixin(name), RegisterCmd)) { commandTable[name] = &mixin(name); } } } } void CommandSystemExecuteCommand(string cmd) { auto result = cmd in commandTable; if (result !is null) { (*result)(); } else { writefln("command %s not found.", cmd); } } The way to extend this seemed fairly straightforward. I did the following things: 1. Wrap function with a Variant, and put that Variant into a struct alongside an array of stringified parameter types (because Parameters!T can't be stored directly). 2. On execution, parse the arguments to their correct types. The problem is, I can't figure out how to actually *call* the function. If it were python, I could construct a tuple with a comprehension and unpack that, but I can't figure out any way to dynamically construct tuples this way in D. Basically, I need some way to turn an array of strings into an argument list at runtime. Is this possible?
Dec 11 2016
On Sunday, 11 December 2016 at 22:00:27 UTC, Kevin Balbas wrote:Basically, I need some way to turn an array of strings into an argument list at runtime. Is this possible?Write (or generate) a helper function that loops over the Parameters!Func tuple and populates it from the strings. Call the helper function. // declare your arguments tuple Parameters!Func args; // populate the arguments foreach(idx, ref arg; args) { arg = to!(typeof(arg))(string_args[idx]); } Func(args); // call the function with that tuple The free sample of my book: https://www.packtpub.com/application-development/d-cookbook has a more in-depth example near the end of it.
Dec 11 2016
On Sunday, 11 December 2016 at 22:18:02 UTC, Adam D. Ruppe wrote:On Sunday, 11 December 2016 at 22:00:27 UTC, Kevin Balbas wrote:I see. I was planning on doing a wrapper-based approach to the function calls if this didn't work out, but I didn't expect it'd be that simple. Thanks for the tip.Basically, I need some way to turn an array of strings into an argument list at runtime. Is this possible?Write (or generate) a helper function that loops over the Parameters!Func tuple and populates it from the strings. Call the helper function. // declare your arguments tuple Parameters!Func args; // populate the arguments foreach(idx, ref arg; args) { arg = to!(typeof(arg))(string_args[idx]); } Func(args); // call the function with that tuple The free sample of my book: https://www.packtpub.com/application-development/d-cookbook has a more in-depth example near the end of it.
Dec 11 2016
import std.traits; import std.stdio; alias FDg = void delegate (string args); FDg[string] cmdlist; void register(DG) (string name, DG dg) if (isCallable!DG) { cmdlist[name] = delegate (string args) { import std.array : split; import std.conv : to; alias Args = Parameters!DG; auto spx = args.split(' '); Args ara; foreach (immutable idx, ref a; ara) { a = spx[idx].to!(typeof(a)); } dg(ara); }; } void main () { register("test", (int a, bool b) { writeln("a=", a, "; b=", b); }); cmdlist["test"]("42 true"); }
Dec 11 2016