Linux Dynamic Loading of shared libraries

Carl Sturtivant via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Tue Jul 29 16:52:25 PDT 2014


Can't retrieve the archive from that URL.
britseyeview.com/plugin101.tar.bz2
Interested, so can you please fix?

On Monday, 10 March 2014 at 11:59:20 UTC, Steve Teale wrote:
> On Sunday, 9 March 2014 at 12:07:22 UTC, Steve Teale wrote:
>
>> Now suppose that my D shared library contains a class, rather 
>> that just module ctors/dtors, how do I go about creating an 
>> instance of that class and using its methods?
>>
> After wandering down several dead-end paths, and help from 
> other contributors, I have finally come up with something that 
> looks like the basis of a plugin pattern for Linux DMD using 
> shared objects (.so files). This is somewhat long for a forum 
> post. You can download this readme and the associated files 
> from britseyeview.com/plugin101.tar.bz2
>
> To get started, you need a base class that provides 
> declarations for all functions that the plugin will be allowed 
> to use externally. Why base class, and not interface? Well I 
> guess because interfaces don't provide any information about 
> data. If you create a shared library based on an interface, 
> then all the shared object methods that reference data in the 
> class that implements the interface fail miserably. I'm sure 
> someone will explain why - probably some obvious thing I have 
> overlooked.
>
> OK, so my base class is:
>
> module plugin;
>
> class Plugin
> {
>    int n;
>    this(int _n) { n = _n; }
>
>    int foo() { return int.min; }
>    void bar() {}
> }
>
>
> The class that implements this base in the shared library is:
>
> module exta;
> import plugin;
> import std.stdio;
> import std.math;
>
> class ExtA: Plugin
> {
>    double d;
>    this(int n) { super(n); d = PI; }
>
>    override int foo() { return ++n; }
>    override void bar() { writefln("Done my thing (%f)", d); }
> }
>
> Plugin getInstance(int n)
> {
>    return new ExtA(n);
> }
>
> shared static this() {
>   writeln("exta.so shared static this");
> }
>
> shared static ~this() {
>   writeln("exta.so shared static ~this");
> }
>
> The module ctor/dtor are included because that has become 
> conventional in discussions about dynamic loading. Otherwise, 
> the so has the class implementation - ExtA, and a shared method 
> to create an instance of same. It includes references to 
> methods in Phobos.
>
> The test program is as follows:
>
> module main;
> import core.runtime;
> import std.stdio;
> import plugin;
>
> extern(C) void* dlsym(void*, const char*);
>
> alias Plugin function(int) pfi;
>
> Plugin getPlugin(string name)
> {
>    void* lib = Runtime.loadLibrary(name~".so");
>    if (lib is null)
>    {
>       writeln("failed to load plugin shared object");
>       return null;
>    }
>
>    void* vp = dlsym(lib, 
> "_D4exta11getInstanceFiZC6plugin6Plugin\0".ptr);
>    if (vp is null)
>    {
>       writeln("plugin creator function not found");
>       return null;
>    }
>    pfi f = cast(pfi) vp;
>    Plugin x = f(42);
>    if (x is null)
>    {
>       writeln("creation of plugin failed");
>       return null;
>    }
>    return x;
> }
>
> void main()
> {
>    Plugin x = getPlugin("exta");
>    int n = x.foo();
>    writefln("n = %d", n);
>    x.bar();
> }
>
> The long symbol name used in the dlsym() call is of course from 
> the .map file generated when the .so file is created
>
> These can be built using the following primitive makefile, 
> whose main purpose is to spell out the required compiler flags:
>
> main :
> 	dmd -c plugin.d
> 	dmd -c -shared -fPIC exta.d
> 	dmd exta.o -shared -defaultlib=libphobos2.so -map
> 	dmd -c main.d
> 	dmd main.o plugin.o -L-ldl -defaultlib=libphobos2.so -L-rpath=.
>
> This assumes that the plugins will be in the same directory as 
> the executable (rpath=.).
>
> Note that there is no call to Runtime.unloadLibrary(). The 
> assumption her is that once the plugin has been loaded it will 
> be there for the duration of the program. If you want to unload 
> it you'll probably have to make sure the plugin object is 
> purged from memory first, and I have not discovered how to do 
> that yet ;=(
>
> Steve



More information about the Digitalmars-d-learn mailing list