www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - How to call function with variable arguments at runtime?

reply Mr. Jonse <Jonse Theory.uni> writes:
I need to store a hetrogeneous array of delegates. How can I do 
this but still call the function with the appropriate number of 
parameters at run time?

I have the parameters as Variant[] params and a function/delegate 
pointer(void* for now).

Normally I'd push the parameters on the stack and use a call, but 
I'm sure D has some ability to do this, like apply(foo, args) 
would be the same as foo(args[0], ..., args[1]).

I'm not concerned about type correctness, it should always be 
consistent between what I call and what is stored.

Thanks.
Oct 09
next sibling parent bauss <jj_1337 live.dk> writes:
On Tuesday, 10 October 2017 at 02:58:45 UTC, Mr. Jonse wrote:
 I need to store a hetrogeneous array of delegates. How can I do 
 this but still call the function with the appropriate number of 
 parameters at run time?

 I have the parameters as Variant[] params and a 
 function/delegate pointer(void* for now).

 Normally I'd push the parameters on the stack and use a call, 
 but I'm sure D has some ability to do this, like apply(foo, 
 args) would be the same as foo(args[0], ..., args[1]).

 I'm not concerned about type correctness, it should always be 
 consistent between what I call and what is stored.

 Thanks.
Not entirely sure what you're wanting to do, but sounds a lot like variadic parameters. https://dlang.org/spec/function.html#variadic mixed with some compile-time terminology.
Oct 10
prev sibling parent reply Marc =?UTF-8?B?U2Now7x0eg==?= <schuetzm gmx.net> writes:
On Tuesday, 10 October 2017 at 02:58:45 UTC, Mr. Jonse wrote:
 I need to store a hetrogeneous array of delegates. How can I do 
 this but still call the function with the appropriate number of 
 parameters at run time?

 I have the parameters as Variant[] params and a 
 function/delegate pointer(void* for now).

 Normally I'd push the parameters on the stack and use a call, 
 but I'm sure D has some ability to do this, like apply(foo, 
 args) would be the same as foo(args[0], ..., args[1]).

 I'm not concerned about type correctness, it should always be 
 consistent between what I call and what is stored.

 Thanks.
Like so? import std.variant; void foo(int a, string b, float c) { import std.stdio; writefln("a = %s, b = %s, c = %s", a, b, c); } auto apply(alias fn)(Variant[] values) { import std.traits : ParameterTypeTuple; import std.conv : emplace; alias Types = ParameterTypeTuple!fn; assert(values.length == Types.length); Types args = void; foreach(i, ref arg; args) { // using emplace instead of assignment here to be fully correct emplace!(typeof(arg))(&arg, values[i].get!(typeof(arg))); } return fn(args); } void main() { Variant[] values = [Variant(1), Variant("Hello world"), Variant(3.14159f)]; apply!foo(values); }
Oct 10
parent Mr. Jonse <Jonse Theory.uni> writes:
On Tuesday, 10 October 2017 at 08:26:37 UTC, Marc Sch├╝tz wrote:
 On Tuesday, 10 October 2017 at 02:58:45 UTC, Mr. Jonse wrote:
 I need to store a hetrogeneous array of delegates. How can I 
 do this but still call the function with the appropriate 
 number of parameters at run time?

 I have the parameters as Variant[] params and a 
 function/delegate pointer(void* for now).

 Normally I'd push the parameters on the stack and use a call, 
 but I'm sure D has some ability to do this, like apply(foo, 
 args) would be the same as foo(args[0], ..., args[1]).

 I'm not concerned about type correctness, it should always be 
 consistent between what I call and what is stored.

 Thanks.
Like so? import std.variant; void foo(int a, string b, float c) { import std.stdio; writefln("a = %s, b = %s, c = %s", a, b, c); } auto apply(alias fn)(Variant[] values) { import std.traits : ParameterTypeTuple; import std.conv : emplace; alias Types = ParameterTypeTuple!fn; assert(values.length == Types.length); Types args = void; foreach(i, ref arg; args) { // using emplace instead of assignment here to be fully correct emplace!(typeof(arg))(&arg, values[i].get!(typeof(arg))); } return fn(args); } void main() { Variant[] values = [Variant(1), Variant("Hello world"), Variant(3.14159f)]; apply!foo(values); }
The problem with this is that the function parameters need to be known. I do not know them. All I have is a function pointer and the arguments in variants. So, it would work off void bar(int, string, float) { } void* foo = &bar; Variant[] values = [Variant(1), Variant("Hello world"), Variant(3.14159f)]; apply(foo, values); So, it has to get the type from the variant at run time and pass the value's appropriately.
Oct 11