On 18-07-2012 06:51, Konstantin J. Chernov wrote:
Hello. When I'm trying to create a class object by using a dlsym-ed
function, I'm getting a segmentation fault after execution of program.

However, if I'm deleting that object before 'return 0' in main (by using
'delete b'), everything is going fine.

I'm just started to learn D after using C++ for more than 5 years, so
some things look really strange for me (especially that 'new
className()' doesn't return a pointer).

What am I doing wrong here? Is there any way to do what I'm trying to do
right way?

Thanks.

test.d:

import std.c.linux.linux;
import std.stdio;
import testclass;

int main(string[] args)
{
     void* handle = dlopen("./testclass.so", RTLD_LAZY | RTLD_LOCAL);
     testclass function(wstring) a;
     a = cast(testclass function(wstring))dlsym(handle, "loadClass");
     testclass b = a("test");
     return 0;
}

testclass.di:

class testclass
{
     this(const wstring loadmsg);
     ~this();
     wstring foo();
};

testclass.d:

import std.stdio;

class testclass
{
     private wstring msg;
     this(const wstring loadmsg)
     {
         writeln("Class constructor");
         this.msg = loadmsg;
     }
     ~this()
     {
     }
     wstring foo()
     {
         return msg;
     }
};

extern(C) testclass loadClass(const wstring loadmsg)
{
     return new testclass(loadmsg);
}


As Jacob said, the D runtime isn't quite ready for shared libraries yet.

What you can do, however, is provide a bit of inversion of control to make the allocation happen from the runtime linked statically to your application:

import std.conv;

alias extern (C) void* function(size_t) Allocator;

extern (C) testclass loadClass(Allocator allocator, const wstring loadmsg)
{
    auto size = __traits(classInstanceSize, testclass);
    auto mem = allocator(size);

    return emplace!testclass(mem[0 .. size], loadmsg);
}

Then in the application:

import core.memory;
import core.sys.posix.dlfcn;
import std.stdio;
import testclass;

void* allocate(size_t size)
{
    return GC.malloc(size);
}

int main(string[] args)
{
    auto h = dlopen("./testclass.so", RTLD_LAZY | RTLD_LOCAL);
auto a = cast(testclass function(Allocator, wstring))dlsym(h, "loadClass");
    auto b = a(&allocate, "test");

    return 0;
}

This should make allocation work, but I haven't actually tested it. Note also that even if it does work, things get more complicated when the class you're allocating has a finalizer, for example (see http://dlang.org/phobos/core_memory.html#FINALIZE).

--
Alex Rønne Petersen
a...@lycus.org
http://lycus.org


Reply via email to