Thread overview | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
February 09, 2014 Resolve function pointers using UDA during CT | ||||
---|---|---|---|---|
| ||||
Hi guys, is there any way to create an function-array during CT using UDAs like the following: module myUdaFunctions; struct MyUDA { string Name; } @MyUDA("Function1") string myFirstUdaFunction(string myString) { // ... do something } @MyUDA("Function2") string mySecondUdaFunction(string myString) { // ... do something } ///////////////////// module myMain; private { string function(string)[string] callbacks; } void main(string[] args) { // during ct: { // do something like this: // // auto u = __traits(getFunctionsByAttribute, "MyUDA") // foreach (myFunction; u) // callbacks[myFunction.GetAttribute("MyUDA").Name] = myFunction } // during runtime: if (args[1] in callbacks) { callbacks[args[1]]("myString"); } } Any way to do something like this? |
February 09, 2014 Re: Resolve function pointers using UDA during CT | ||||
---|---|---|---|---|
| ||||
Posted in reply to Tim Volckmann | On Sunday, 9 February 2014 at 12:48:36 UTC, Tim Volckmann wrote:
> Any way to do something like this?
No, associative arrays cannot be transferred from compile-time to runtime yet, due to implementation issues. The next best thing you can do is to use a module constructor with a generated body that fills the AA.
|
February 09, 2014 Re: Resolve function pointers using UDA during CT | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jakob Ovrum | On Sunday, 9 February 2014 at 13:03:47 UTC, Jakob Ovrum wrote: > On Sunday, 9 February 2014 at 12:48:36 UTC, Tim Volckmann wrote: >> Any way to do something like this? > > No, associative arrays cannot be transferred from compile-time to runtime yet, due to implementation issues. The next best thing you can do is to use a module constructor with a generated body that fills the AA. You mean using static this as follows?: module myMain; private { string function(string)[string] callbacks; } static this() { { // do something like this: // // auto u = __traits(getFunctionsByAttribute, "MyUDA") // foreach (myFunction; u) // callbacks[myFunction.GetAttribute("MyUDA").Name] = myFunction } } void main(string[] args) { if (args[1] in callbacks) { callbacks[args[1]]("myString"); } } That's also possible... but how can I find all functions with MyUDA? |
February 09, 2014 Re: Resolve function pointers using UDA during CT | ||||
---|---|---|---|---|
| ||||
Posted in reply to Tim Volckmann | On Sunday, 9 February 2014 at 13:10:14 UTC, Tim Volckmann wrote:
> That's also possible... but how can I find all functions with MyUDA?
There is no global list of symbols with a given UDA, you have to search using __traits(allMembers) and such. the allMembers trait can be used on modules.
If the functions with the UDAs are in user-defined modules, you need to have the user specify those modules (so a module constructor is not an option):
---
import mylib;
import usermod1, usermod2;
void main()
{
registerFunctions!(usermod1, usermod2)();
}
---
|
February 09, 2014 Re: Resolve function pointers using UDA during CT | ||||
---|---|---|---|---|
| ||||
Posted in reply to Tim Volckmann | On Sun, Feb 9, 2014 at 2:10 PM, Tim Volckmann <timvol@ymail.com> wrote: > That's also possible... but how can I find all functions with MyUDA? Here is a possibility: *********** module myUDAFunctions; import std.stdio; struct MyUDA { string Name; } @MyUDA("Function1") string myFirstUdaFunction(string myString) { writeln("MyFirstUDAFunction called with ", myString); return "first"; } @MyUDA("Function2") string mySecondUdaFunction(string myString) { writeln("MySecondUDAFunction called with ", myString); return "second"; } ************** module myMain; import std.stdio; import std.traits; import std.typetuple; import myUDAFunctions; private { string function(string)[string] callbacks; } static this() { // Getting all symbols from module myUDAFunctions // Beware: we get strings, not aliases. // Hence the mixin() afterwards to inject them in our code foreach(symbol; __traits(allMembers, myUDAFunctions)) static if (isCallable!(mixin(symbol))) // Found some callable { // Extracting attributes foreach(attribute; __traits(getAttributes, mixin(symbol))) { // Finding those which are MyUDA's static if (is(typeof(attribute) == MyUDA)) callbacks[attribute.Name] = mixin("&" ~ symbol); } } } void main(string[] args) { writeln("Callbacks: ", callbacks); writeln("Args: ", args); if (args[1] in callbacks) { writeln(args[1], " known in callbacks"); callbacks[args[1]]("myString"); } } ************ it's a be cumbersome, you should extract the pattern and put it in a template with MyUDA and the module name as parameters. Note the ` callbacks[attribute.Name] = mixin("&" ~ symbol);` line: since `symbol` is a string, we have to mix it in the code. And since `functionName` is seen as a call to `functionName` and not as the function itself, I had to put an `&` before it (the generated code is `callbakcs["Func1"] = &Fun1;`, for example) |
February 09, 2014 Re: Resolve function pointers using UDA during CT | ||||
---|---|---|---|---|
| ||||
On Sun, Feb 9, 2014 at 2:48 PM, Philippe Sigaud <philippe.sigaud@gmail.com> wrote:
> import std.stdio;
> import std.traits;
> import std.typetuple;
Hmm, std.typetuple is not necessary. And std.traits is used only to import `isCallable`.
|
February 09, 2014 Re: Resolve function pointers using UDA during CT | ||||
---|---|---|---|---|
| ||||
Posted in reply to Philippe Sigaud | On Sunday, 9 February 2014 at 13:48:36 UTC, Philippe Sigaud wrote:
> callbacks[attribute.Name] = mixin("&" ~ symbol);
callbacks[attribute.Name] = &mixin(symbol);
|
February 23, 2014 Re: Resolve function pointers using UDA during CT | ||||
---|---|---|---|---|
| ||||
Posted in reply to Philippe Sigaud | On Sunday, 9 February 2014 at 13:48:36 UTC, Philippe Sigaud wrote:
> On Sun, Feb 9, 2014 at 2:10 PM, Tim Volckmann <timvol@ymail.com> wrote:
>
>> That's also possible... but how can I find all functions with MyUDA?
>
> Here is a possibility:
>
> ***********
> module myUDAFunctions;
>
> import std.stdio;
>
> struct MyUDA
> {
> string Name;
> }
>
> @MyUDA("Function1")
> string myFirstUdaFunction(string myString)
> {
> writeln("MyFirstUDAFunction called with ", myString);
> return "first";
> }
>
> @MyUDA("Function2")
> string mySecondUdaFunction(string myString)
> {
> writeln("MySecondUDAFunction called with ", myString);
> return "second";
> }
> **************
> module myMain;
>
> import std.stdio;
> import std.traits;
> import std.typetuple;
>
> import myUDAFunctions;
>
> private
> {
> string function(string)[string] callbacks;
> }
>
> static this()
> {
> // Getting all symbols from module myUDAFunctions
> // Beware: we get strings, not aliases.
> // Hence the mixin() afterwards to inject them in our code
> foreach(symbol; __traits(allMembers, myUDAFunctions))
> static if (isCallable!(mixin(symbol))) // Found some callable
> {
> // Extracting attributes
> foreach(attribute; __traits(getAttributes, mixin(symbol)))
> {
> // Finding those which are MyUDA's
> static if (is(typeof(attribute) == MyUDA))
> callbacks[attribute.Name] = mixin("&" ~ symbol);
> }
> }
> }
>
> void main(string[] args)
> {
> writeln("Callbacks: ", callbacks);
> writeln("Args: ", args);
> if (args[1] in callbacks)
> {
> writeln(args[1], " known in callbacks");
> callbacks[args[1]]("myString");
> }
> }
> ************
>
> it's a be cumbersome, you should extract the pattern and put it in a
> template with MyUDA and the module name as parameters.
>
> Note the ` callbacks[attribute.Name] = mixin("&" ~ symbol);` line:
>
> since `symbol` is a string, we have to mix it in the code.
> And since `functionName` is seen as a call to `functionName` and not
> as the function itself, I had to put an `&` before it
> (the generated code is `callbakcs["Func1"] = &Fun1;`, for example)
Works as expected, thanks Jakob and Philippe!
|
Copyright © 1999-2021 by the D Language Foundation