Jump to page: 1 2
Thread overview
Call function by its string name
Oct 19, 2013
aldanor
Oct 19, 2013
John Colvin
Oct 19, 2013
aldanor
Oct 19, 2013
Meta
Oct 19, 2013
aldanor
Oct 19, 2013
Meta
Oct 19, 2013
John Colvin
Oct 19, 2013
aldanor
Oct 19, 2013
Kenji Hara
Oct 19, 2013
aldanor
Oct 19, 2013
Artur Skawina
October 19, 2013
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?
October 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.
October 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:
>> 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.

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).
October 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:
>> 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.
>
> 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).

What about mixins?
October 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:
>> 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:
>>>> 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.
>>
>> 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).
>
> What about mixins?

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?
October 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:
>> 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.
>
> 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).

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.
October 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:
>> 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:
>>>> 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.
>>
>> 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).
>
> 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.

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.
October 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.
>


October 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.
October 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
« First   ‹ Prev
1 2