Thread overview
undefined symbol: _Dmain when loading library at runtime on Linux
Sep 29, 2013
FreeSlave
Sep 29, 2013
David Nadlinger
Sep 30, 2013
FreeSlave
September 29, 2013
//mod.d:

module mod;

export extern(C) int testThrow()
{
    throw new Exception("Just a test");
}

//main.d:

import std.stdio;
import std.c.linux.linux;
import std.string : toStringz;
import std.conv : to;

int main(string args[])
{
    version(Binding)
    {
        version(LDC)
        {
            string name = "./libmodldc.so";
        }
        else
        {
            string name = "./libmod.so";
        }
        void* handle = dlopen(toStringz(name), RTLD_LAZY);
        if (!handle)
        {
            writeln(to!string(dlerror()));
            return 1;
        }
        auto testThrow = cast(void function())dlsym(handle, toStringz("testThrow"));
        if (!testThrow)
        {
            writeln(to!string(dlerror()));
            return 1;
        }
    }
    else
    {
        import mod;
    }

    try {
        testThrow();
    }
    catch(Exception e)
    {
        writeln(e.msg);
    }

    return 0;
}

Script to build them all and start executables in place:

#! /bin/bash
export LD_LIBRARY_PATH=.
ldmd2 -shared -fPIC mod.d -oflibmodldc.so
ldmd2 main.d -L-L. -L-lmodldc -ofmainldc
ldmd2 main.d -version=Binding -ofmainldcbind

dmd -shared -fPIC mod.d -oflibmod.so
dmd main.d -L-L. -L-lmod -ofmain
dmd main.d -version=Binding -ofmainbind -L-ldl

./main
./mainbind
./mainldc
./mainldcbind

Both main and mainldc work fine (those which was linked against shared library). But when I start "bind" version compiled by ldmd2 I got error:

./libmodldc.so: undefined symbol: _Dmain

If I add -L--export-dynamic option to command line then it works fine. But dmd does not require this option - mainbind has correct output.

Another strange thing is that ldmd2 does not require linking against dlfcn library.
September 29, 2013
The short answer is: Shared D libraries, especially dynamically loading them, is not supported by LDC. We are going implement this once upstream druntime actually supports runtime loading (2.064). So, even the versions that "work fine" do so just by accident. There are much bigger problems that this, even with compile-time linked shared libraries.

dlfcn - you mean libdl?

David
September 30, 2013
On Sunday, 29 September 2013 at 23:40:21 UTC, David Nadlinger wrote:
> The short answer is: Shared D libraries, especially dynamically loading them, is not supported by LDC. We are going implement this once upstream druntime actually supports runtime loading (2.064). So, even the versions that "work fine" do so just by accident. There are much bigger problems that this, even with compile-time linked shared libraries.
>
> dlfcn - you mean libdl?
>
> David

Yes, libdl. dlfcn if header's name. Well, this "by accident" is not so bad, I've just checked dynamic loading of C++ class in ldmd2 - it works. But I'm not sure how to build C++ library to set D function as exception handler properly (for rethrowing). It worked with dmd in this way:
//dmd cppexception.d -c
extern(C) void cppRethrower()
{
    throw new Exception("Cpp exception");
}
//g++ cppfiles.cpp cppexception.o
extern "C" { void cppRethrower(); }
std::set_terminate(cppRethrower); //somewhere

Anyway, wait for good support of shared libraries by all D compiler, I'm very interested in that because I write library helping to load plugins at runtime ( https://bitbucket.org/FreeSlave/dido )