| Thread overview | ||||||
|---|---|---|---|---|---|---|
|
December 11, 2016 Calling arbitrary functions at runtime? | ||||
|---|---|---|---|---|
| ||||
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?
| ||||
December 11, 2016 Re: Calling arbitrary functions at runtime? | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Kevin Balbas | 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. | |||
December 11, 2016 Re: Calling arbitrary functions at runtime? | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Kevin Balbas | 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");
}
| |||
December 11, 2016 Re: Calling arbitrary functions at runtime? | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Adam D. Ruppe | 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:
>> 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.
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.
| |||
Copyright © 1999-2021 by the D Language Foundation
Permalink
Reply