On Friday, 14 March 2014 at 06:54:34 UTC, Steve Teale wrote:
On Thursday, 13 March 2014 at 21:20:10 UTC, Tolga Cakiroglu

It is not just a shut-down artefact, since if I repeat the exercise with an exemplar class instead of an interface, then it will work.


OK, so here's an example using an exemplar base class instead of an interface. This includes making the exemplar class implement an interface.

Here's the exemplar class, and another class that references an instance of it:

module bc;
import std.stdio;

interface I
{
   string saySomething();
}

class Bc: I
{
   string saySomething() { return null; };
}

class Other
{
   I target;

   this(I i) { target = i; }

void invokeWithCast() { writeln((cast(Bc) target).saySomething()); }
   void invoke() { writeln(target.saySomething()); }
}

Then the plugin:

module plugin;
import bc;
import std.stdio;

class Plugin: Bc
{
   this() { writeln("plugin ctor"); }

   override string saySomething() { return "I am plugin"; }
}

Bc getInstance()
{
   return new Plugin();
}

And the program:

module main;
import core.runtime;
import std.stdio;
import bc;

extern(C) void* dlsym(void*, const char*);

alias Bc function() pfi;

Bc getPlugin(string name)
{
   void* lib = Runtime.loadLibrary(name~".so");

   void* vp = dlsym(lib, "_D6plugin11getInstanceFZC2bc2Bc\0".ptr);
   pfi f = cast(pfi) vp;
   Bc x = f();
        return x;
}

void main()
{
   Bc x = getPlugin("plugin");
   writeln(x.saySomething());    // OK
   Other other = new Other(x);
   other.invokeWithCast();       // OK
   other.invoke();               // Crash
}

Built with:

main : bc.d main.d
        dmd -c bc.d
        dmd -c main.d
dmd main.o bc.o -L-L/usr/local/lib -L-ldl -L-lgtkd-2 -defaultlib=libphobos2.so -L-rpath=.

plugin : plugin.d
        dmd -c -shared -fPIC plugin.d
        dmd plugin.o -shared -defaultlib=libphobos2.so -map

clean :
        rm *.o
        rm main
        rm plugin.so

Output:

steve@steve-desktop:~/scratch/pibc$ ./main
plugin ctor
I am plugin
I am plugin
Segmentation fault (core dumped)

If you comment out the last call via the interface instance with no cast, the program exits cleanly. So the problem does seem to relate to interfaces.

So you can do it, but if the base class conforms to some interface, then you have to special-case calls to the interface functions. That rather destroys the utility of classes like Other which provide services to the installed plugin.

My gut-feeling question is "is the vtable in the program or the plugin, and does this vary when the plugin implements an interface?"

I'm hoping Martin Nowak might join in this discussion.

Steve

Reply via email to