Skip to content

Instantly share code, notes, and snippets.

@run-dlang
Created May 15, 2018 21:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save run-dlang/18845c9df3d73e45c945feaccfebfcdc to your computer and use it in GitHub Desktop.
Save run-dlang/18845c9df3d73e45c945feaccfebfcdc to your computer and use it in GitHub Desktop.
Code shared from run.dlang.io.
import std.stdio;
class SomeClass
{
void memberFunc(int x, float y)
{
writeln("SomeClass.memberFunc(", x, ", ", y, ")");
}
}
struct SomeStruct
{
void memberFunc(int x, float y)
{
writeln("SomeStruct.memberFunc(", x, ", ", y, ")");
}
}
void notMemberFunc1(SomeClass s, int x, float y)
{
s.memberFunc(x, y);
}
void notMemberFunc2(SomeStruct* s, int x, float y)
{
s.memberFunc(x, y);
}
auto makeDelegate(alias fun, T)(T obj)
if (is(T == class))
{
void delegate(int, float) result;
static class Shim : T
{
final void fwd(int x, float y) { return fun(this, x, y); }
}
result.ptr = cast(void*) obj;
result.funcptr = cast(void function(int, float)) &Shim.fwd;
return result;
}
auto makeDelegate(alias fun, T)(T* obj)
if (is(T == struct))
{
void delegate(int, float) result;
static struct Shim
{
void fwd(int x, float y) { fun(cast(T*) &this, x, y); }
}
result.ptr = obj;
result.funcptr = cast(void function(int, float)) &Shim.fwd;
return result;
}
void main()
{
auto x = new SomeClass;
auto y = makeDelegate!notMemberFunc1(x);
y(41, 42);
auto z = new SomeStruct;
y = makeDelegate!notMemberFunc2(z);
y(43, 44);
}
@marler8997
Copy link

Mike Parker sent me an email that indicated this code "makes no additional alocations or indirections". However, this is not the case. The code inside the fwd function is an indirection, a chunk of code that MUST exist at runtime in order to forward the a call to a delegate function to the real function being called. In fact, since you have defined the functions nonMemberFunc1 and nonMemberFunc2 as normal functions, you will always have to create a "conversion" function to forward a delegate call to the actual function. In order for a library solution to not introduce "indirection", you'll need to modify the function definition itself so that it matches the delegate ABI. The only way to do this currently is to define those functions inside a dummy struct/class.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment