digitalmars.D - Call function by its string name
- aldanor (6/6) Oct 19 2013 I was wondering if it was possible to call D functions by their
- John Colvin (4/10) Oct 19 2013 You could make an associative array of function pointers with
- aldanor (9/19) Oct 19 2013 Thanks for the reply, this is something I thought about of
- Meta (2/22) Oct 19 2013 What about mixins?
- aldanor (4/30) Oct 19 2013 But the function/method names are only known in runtime
- Meta (3/6) Oct 19 2013 Sorry, I misread and thought you said the strings *were* known at
- John Colvin (9/29) Oct 19 2013 No matter what happens, if you want to take a runtime string and
- aldanor (4/37) Oct 19 2013 Yes, in my case it's very specific, let's say I receive a string
- Kenji Hara (51/54) Oct 19 2013 A quick sample code to make a table of function pointers at compiler tim...
- aldanor (3/5) Oct 19 2013 That looks like exactly the kind of D-fu that I need, great
- Artur Skawina (30/31) Oct 19 2013 You can build a name->funcPtr table at CT and look up at RT.
I was wondering if it was possible to call D functions by their names (strings that are not known at compile time) and couldn't find the answer anywhere in the documentation. Kinda like we can instantiate objects with Object.factory, would it be possible to somehow do the same with module-level functions? Or maybe with non-static class methods?
Oct 19 2013
On Saturday, 19 October 2013 at 16:33:11 UTC, aldanor wrote:I was wondering if it was possible to call D functions by their names (strings that are not known at compile time) and couldn't find the answer anywhere in the documentation. Kinda like we can instantiate objects with Object.factory, would it be possible to somehow do the same with module-level functions? Or maybe with non-static class methods?You could make an associative array of function pointers with strings as keys. Probably not the best solution but it should work.
Oct 19 2013
On Saturday, 19 October 2013 at 16:56:50 UTC, John Colvin wrote:On Saturday, 19 October 2013 at 16:33:11 UTC, aldanor wrote:Thanks for the reply, this is something I thought about of course. But what if I have hundreds of functions to dispatch to? The current (C) implementation does exactly that, autogenerates a sort of an associative array, but that's very ugly and requires an extra preprocessing step. I was thinking runtime reflections can help do this, but I'm not quite sure where to start (and there is also the performance question).I was wondering if it was possible to call D functions by their names (strings that are not known at compile time) and couldn't find the answer anywhere in the documentation. Kinda like we can instantiate objects with Object.factory, would it be possible to somehow do the same with module-level functions? Or maybe with non-static class methods?You could make an associative array of function pointers with strings as keys. Probably not the best solution but it should work.
Oct 19 2013
On Saturday, 19 October 2013 at 17:17:47 UTC, aldanor wrote:On Saturday, 19 October 2013 at 16:56:50 UTC, John Colvin wrote:What about mixins?On Saturday, 19 October 2013 at 16:33:11 UTC, aldanor wrote:Thanks for the reply, this is something I thought about of course. But what if I have hundreds of functions to dispatch to? The current (C) implementation does exactly that, autogenerates a sort of an associative array, but that's very ugly and requires an extra preprocessing step. I was thinking runtime reflections can help do this, but I'm not quite sure where to start (and there is also the performance question).I was wondering if it was possible to call D functions by their names (strings that are not known at compile time) and couldn't find the answer anywhere in the documentation. Kinda like we can instantiate objects with Object.factory, would it be possible to somehow do the same with module-level functions? Or maybe with non-static class methods?You could make an associative array of function pointers with strings as keys. Probably not the best solution but it should work.
Oct 19 2013
On Saturday, 19 October 2013 at 17:19:25 UTC, Meta wrote:On Saturday, 19 October 2013 at 17:17:47 UTC, aldanor wrote:But the function/method names are only known in runtime (dispatched by user input parser), so mixins wouldn't really help, or am I missing something?On Saturday, 19 October 2013 at 16:56:50 UTC, John Colvin wrote:What about mixins?On Saturday, 19 October 2013 at 16:33:11 UTC, aldanor wrote:Thanks for the reply, this is something I thought about of course. But what if I have hundreds of functions to dispatch to? The current (C) implementation does exactly that, autogenerates a sort of an associative array, but that's very ugly and requires an extra preprocessing step. I was thinking runtime reflections can help do this, but I'm not quite sure where to start (and there is also the performance question).I was wondering if it was possible to call D functions by their names (strings that are not known at compile time) and couldn't find the answer anywhere in the documentation. Kinda like we can instantiate objects with Object.factory, would it be possible to somehow do the same with module-level functions? Or maybe with non-static class methods?You could make an associative array of function pointers with strings as keys. Probably not the best solution but it should work.
Oct 19 2013
On Saturday, 19 October 2013 at 17:28:44 UTC, aldanor wrote:But the function/method names are only known in runtime (dispatched by user input parser), so mixins wouldn't really help, or am I missing something?Sorry, I misread and thought you said the strings *were* known at compile time.
Oct 19 2013
On Saturday, 19 October 2013 at 17:17:47 UTC, aldanor wrote:On Saturday, 19 October 2013 at 16:56:50 UTC, John Colvin wrote:No matter what happens, if you want to take a runtime string and work out what function it corresponds to then you're going to have to use some sort of string matching. Unless you have a very specific function name format then a hash is probably the fastest way to do this, especially in the case of hundreds of functions. D's compile-time reflection could probably make building the associative array neat and easy.On Saturday, 19 October 2013 at 16:33:11 UTC, aldanor wrote:Thanks for the reply, this is something I thought about of course. But what if I have hundreds of functions to dispatch to? The current (C) implementation does exactly that, autogenerates a sort of an associative array, but that's very ugly and requires an extra preprocessing step. I was thinking runtime reflections can help do this, but I'm not quite sure where to start (and there is also the performance question).I was wondering if it was possible to call D functions by their names (strings that are not known at compile time) and couldn't find the answer anywhere in the documentation. Kinda like we can instantiate objects with Object.factory, would it be possible to somehow do the same with module-level functions? Or maybe with non-static class methods?You could make an associative array of function pointers with strings as keys. Probably not the best solution but it should work.
Oct 19 2013
On Saturday, 19 October 2013 at 17:35:53 UTC, John Colvin wrote:On Saturday, 19 October 2013 at 17:17:47 UTC, aldanor wrote:Yes, in my case it's very specific, let's say I receive a string "fun" and want to call do_fun(args) or Obj.do_fun(args). Thanks, I'll try looking into compile-time reflection.On Saturday, 19 October 2013 at 16:56:50 UTC, John Colvin wrote:No matter what happens, if you want to take a runtime string and work out what function it corresponds to then you're going to have to use some sort of string matching. Unless you have a very specific function name format then a hash is probably the fastest way to do this, especially in the case of hundreds of functions. D's compile-time reflection could probably make building the associative array neat and easy.On Saturday, 19 October 2013 at 16:33:11 UTC, aldanor wrote:Thanks for the reply, this is something I thought about of course. But what if I have hundreds of functions to dispatch to? The current (C) implementation does exactly that, autogenerates a sort of an associative array, but that's very ugly and requires an extra preprocessing step. I was thinking runtime reflections can help do this, but I'm not quite sure where to start (and there is also the performance question).I was wondering if it was possible to call D functions by their names (strings that are not known at compile time) and couldn't find the answer anywhere in the documentation. Kinda like we can instantiate objects with Object.factory, would it be possible to somehow do the same with module-level functions? Or maybe with non-static class methods?You could make an associative array of function pointers with strings as keys. Probably not the best solution but it should work.
Oct 19 2013
A quick sample code to make a table of function pointers at compiler time. module test; import std.typetuple; // calculate compile-time tuple of functions declared in 'mod' module template getFunctions(alias mod) { template filterPred(string name) { // if the 'name' is really a function, returns true enum filterPred = is(typeof(__traits(getMember, mod, name)) == function); } alias names = Filter!(filterPred, __traits(allMembers, mod)); template mapPred(string name) { alias mapPred = TypeTuple!(__traits(getMember, mod, name))[0]; } alias getFunctions = staticMap!(mapPred, names); } // gather functions from modname, then make function pointer table auto makeTable(alias modname)() { mixin("import "~modname~";"); mixin("alias funcs = getFunctions!("~modname~");"); immutable(void*)[] make(size_t n)() { static if (n < funcs.length) return cast(immutable(void*))&(funcs[n]) ~ make!(n+1)(); else return []; } immutable(void*)[funcs.length] tbl = make!0()[0 .. funcs.length]; return tbl; } // make function pointer table immutable func_table = makeTable!"decl"(); void main() { (cast(void function())func_table[0])(); assert((cast(int function(int))func_table[1])(10) == 20); } module decl; void fn() { import std.stdio; writeln("call fn"); } int bar(int n) { import std.stdio; writeln("call bar"); return n * 2; } ---- $ dmd decl.d -run test call fn call bar There's no runtime cost to make function pointer table. Kenji Hara 2013/10/20 aldanor <i.s.smirnov gmail.com>Yes, in my case it's very specific, let's say I receive a string "fun" and want to call do_fun(args) or Obj.do_fun(args). Thanks, I'll try looking into compile-time reflection.
Oct 19 2013
On Saturday, 19 October 2013 at 17:58:36 UTC, Kenji Hara wrote:A quick sample code to make a table of function pointers at compiler time.That looks like exactly the kind of D-fu that I need, great example, thanks Kenji!
Oct 19 2013
On 10/19/13 18:33, aldanor wrote:I was wondering if it was possible to call D functions by their names (strings that are not known at compile time) and couldn't find the answer anywhere in the documentation. Kinda like we can instantiate objects with Object.factory, would it be possible to somehow do the same with module-level functions? Or maybe with non-static class methods?You can build a name->funcPtr table at CT and look up at RT. You could also let the dynamic linker handle it, but that approach will be less portable. For example, this will work in linux: ========================================================================== // gdc dlopen1.d -o dlopen1 -ldl -Wl,--export-dynamic && ./dlopen1 f1 2 import std.stdio; alias int function(int) FT; int dummy42(int a); int f1(int a) { int i = 42+a; writeln(i); return i; } int f2(int a) { int i = 17*a; writeln(i); return i; } int main(string[] argv) { import std.conv, std.array; auto mnamehack = replace(dummy42.mangleof, "7dummy42", to!string(argv[1].length)~argv[1])~"\0"; auto fp = cast(FT)dlsym(RTLD_DEFAULT, mnamehack.ptr); if (!fp) { writeln(to!string(dlerror())); return 1; } return fp(to!int(argv[2])); } extern (C) void* dlsym(const void* handle, const char* symbol); extern (C) const(char)* dlerror(); enum RTLD_DEFAULT = null; ========================================================================== Of course this is just an example - the name mangling is hack (maybe there is something in druntime/phobos that could help), but enough for many cases where you just want to choose from a known set of functions/methods at RT. artur
Oct 19 2013