Plugins and D programs

Steve Teale steve.teale at britseyeview.com
Fri Mar 14 00:46:24 PDT 2014


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 at 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


More information about the Digitalmars-d mailing list