Thread overview | ||||||
---|---|---|---|---|---|---|
|
March 17, 2015 Understanding behavior of member functions loaded at runtime | ||||
---|---|---|---|---|
| ||||
============================================================ module dll; struct S { int a; int b; int method() { return a + b; } } ============================================================ module test; import core.sys.posix.dlfcn; import core.stdc.stdio; import dll; pragma(lib, "dl"); pragma(mangle, S.method.mangleof) __gshared int function(S* self) paramMethod; __gshared int function() noparamMethod; void main(string[] args) { void* lib = dlopen("dll.so", RTLD_LAZY); string funcName = S.method.mangleof; noparamMethod = cast(typeof(noparamMethod)) dlsym(lib, funcName.ptr); paramMethod = cast(typeof(paramMethod)) dlsym(lib, funcName.ptr); int result = noparamMethod(); printf("%d\n", result); S s = { 1, 1 }; result = paramMethod(&s); printf("%d\n", result); result = s.method(); // Symbol resolved because of pragma(mangle) printf("%d\n", result); // Error: function dll.S.method () is not callable using argument types (S*) //result = S.method(&s); //printf("%d\n", result); } ============================================================ dmd -fPIC -shared -defaultlib=libphobos2.so dll.d dmd -defaultlib=libphobos2.so -L-rpath=. test.d the output is 0 2 Segmentation fault My questions are 1) Why does 'noparamMethod" return 0? I assume that 'this' points to S.init but how does it know where to find it? What's going on? 2) typeof(S.method) is "int()". Why's that? In C++ it would have been "int(S* const)" and I though in D it would have been "int(S*)" 2.1) Is this related to why case 4 doesn't compile? 3) Why does case 3 crash? I assume it's because there is no argument so 'this' is null, but wouldn't the call be translated to "S.method(&s)"? |
March 18, 2015 Re: Understanding behavior of member functions loaded at runtime | ||||
---|---|---|---|---|
| ||||
Posted in reply to Maeriden | You violate the ABI, try to use delegates instead of functions. |
March 18, 2015 Re: Understanding behavior of member functions loaded at runtime | ||||
---|---|---|---|---|
| ||||
Posted in reply to Kagamin | On Wednesday, 18 March 2015 at 07:57:39 UTC, Kagamin wrote:
> You violate the ABI, try to use delegates instead of functions.
I'm sorry,I don't understand what you mean.
|
March 18, 2015 Re: Understanding behavior of member functions loaded at runtime | ||||
---|---|---|---|---|
| ||||
Posted in reply to Maeriden | On 03/18/2015 09:02 AM, Maeriden wrote:
> On Wednesday, 18 March 2015 at 07:57:39 UTC, Kagamin wrote:
>> You violate the ABI, try to use delegates instead of functions.
>
> I'm sorry,I don't understand what you mean.
The types that you cast to are not correct. In D, callable member function pointers are delegates, a type that combines a function pointer and a context.
import std.stdio;
struct S
{
int a;
int b;
int method()
{
writeln(&a);
return a + b;
}
}
void main()
{
auto s = S(1, 1);
auto func = &s.method; // <-- note lowercase s
static assert ( is (typeof(func) == int delegate()));
static assert (!is (typeof(func) == int function())); // <-- note !
assert(func() == 2);
}
The function pointer and the context pointer are available through the .funcptr and .ptr properties of the delegate. It is possible to make a delegate by setting those properties:
void main()
{
auto s = S(1, 1);
auto func = &S.method; // <-- note uppercase S
static assert (!is (typeof(func) == int delegate())); // <-- note !
static assert ( is (typeof(func) == int function()));
int delegate() d; // let's make a delegate
d.funcptr = func;
d.ptr = &s;
assert(d() == 2);
}
Ali
|
Copyright © 1999-2021 by the D Language Foundation