www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 13476] New: [REG2.065] Writing stubs for dynamically loaded

https://issues.dlang.org/show_bug.cgi?id=13476

          Issue ID: 13476
           Summary: [REG2.065] Writing stubs for dynamically loaded
                    functions no longer works. (circular reference)
           Product: D
           Version: D2
          Hardware: All
                OS: All
            Status: NEW
          Keywords: rejects-valid
          Severity: regression
          Priority: P1
         Component: DMD
          Assignee: nobody puremagic.com
          Reporter: Marco.Leise gmx.de

When loading dynamic libraries we often only need a few functions out of a
large set. Instead of eagerly loading all the symbols, we defer lookup until we
actually call that function. This is done by initially having the function
pointers set to a stub, that replaces its pointer with the correct one loaded
via e.g. `dlsym` and calls it. The same applies to "extensions": functions that
may or may not be present in a shared object.
In DMD 2.064 this code worked fine:

    import std.traits;

    __gshared nothrow extern(C) void function(int) someFunc = &Stub!someFunc;

    nothrow extern(C) auto Stub(alias func)(ParameterTypeTuple!func args)
    {
        import core.stdc.stdio;
        printf("Loading %s...\n", func.stringof.ptr);
        nothrow extern(C) void function(int) impl = (i) {
            printf("Dummy function called with %d\n", i);
        };
        return (func = impl)(args);
    }

    void main()
    {
        someFunc(42);
        someFunc(43);
    }

Since 2.065 though, it produces a circular reference error:

    main.d(3): Error: circular reference to 'main.someFunc'

The following code - if you think about it - exhibits the same theoretical
circular dependency but still works:

    import std.traits;

    __gshared nothrow extern(C) void function(int) someFunc = &Stub!someFuncP;
    __gshared nothrow extern(C) void function(int)* someFuncP = &someFunc;

    nothrow extern(C) void Stub(alias func)(int args)
    {
        import core.stdc.stdio;
        enum name = func.stringof[0 .. $-1];
        printf("Loading %s...\n", name.ptr);
        nothrow extern(C) void function(int) impl = (i) {
            printf("Dummy function called with %d\n", i);
        };
        return (*func = impl)(args);
    }

    void main()
    {
        someFunc(42);
        someFunc(43);
    }

--
Sep 14 2014