Bug 13476 – [REG2.065] Writing stubs for dynamically loaded functions no longer works. (circular reference)
Status
RESOLVED
Resolution
FIXED
Severity
regression
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2014-09-14T23:18:00Z
Last change time
2015-02-18T03:37:00Z
Keywords
pull, rejects-valid
Assigned to
nobody
Creator
Marco.Leise
Comments
Comment #0 by Marco.Leise — 2014-09-14T23:18:07Z
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);
}