Thread overview
Understanding behavior of member functions loaded at runtime
Mar 17, 2015
Maeriden
Mar 18, 2015
Kagamin
Mar 18, 2015
Maeriden
Mar 18, 2015
Ali Çehreli
March 17, 2015
============================================================
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
You violate the ABI, try to use delegates instead of functions.
March 18, 2015
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
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