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