digitalmars.D.learn - Segmentation fault while creating a class object by dlsym-ed function
- Konstantin J. Chernov (54/54) Jul 17 2012 Hello. When I'm trying to create a class object by using a
- Jacob Carlborg (5/14) Jul 17 2012 Dynamic libraries aren't properly supported by the runtime.
- Konstantin J. Chernov (4/8) Jul 18 2012 That's terrible:(
- Jacob Carlborg (5/13) Jul 18 2012 No, not that I can think of for now. But it's a known problem that is
- bearophile (4/11) Jul 18 2012 And usually you don't need to write .di files in D.
- =?UTF-8?B?QWxleCBSw7hubmUgUGV0ZXJzZW4=?= (38/89) Jul 18 2012 As Jacob said, the D runtime isn't quite ready for shared libraries yet.
- Konstantin J. Chernov (53/53) Jul 18 2012 Thank you for your replies!
- Alexandr Druzhinin (5/5) Jul 18 2012 Probably you mean the same problem that is described in the thread
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); }
Jul 17 2012
On 2012-07-18 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).Classes are always references.What am I doing wrong here? Is there any way to do what I'm trying to do right way?Dynamic libraries aren't properly supported by the runtime. -- /Jacob Carlborg
Jul 17 2012
That's terrible:( It's so nice to make an interface, and create classes that inherit this interface dynamically, without linking... Maybe there's another way?What am I doing wrong here? Is there any way to do what I'm trying to do right way?Dynamic libraries aren't properly supported by the runtime.
Jul 18 2012
On 2012-07-18 10:17, Konstantin J. Chernov wrote:No, not that I can think of for now. But it's a known problem that is being worked on: https://github.com/dawgfoto/druntime/tree/SharedRuntime -- /Jacob CarlborgThat's terrible:( It's so nice to make an interface, and create classes that inherit this interface dynamically, without linking... Maybe there's another way?What am I doing wrong here? Is there any way to do what I'm trying to do right way?Dynamic libraries aren't properly supported by the runtime.
Jul 18 2012
Konstantin J. Chernov:testclass.di: class testclass { this(const wstring loadmsg); ~this(); wstring foo(); };And usually you don't need to write .di files in D. Bye, bearophile
Jul 18 2012
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 alex lycus.org http://lycus.org
Jul 18 2012
Thank you for your replies! I've found a working solution - all I needed is to change wstring to const wstring, and pass it not as func("something"), but as wstring tmp = "something"; func(tmp); That's really odd, because I don't understand, how those changes made segfault disappear. Here's the working code: 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(const wstring) a; a = cast(testclass function(const wstring))dlsym(handle, "loadClass"); wstring tmp = "Test"; testclass b = a(tmp); 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); } dmd test.d -L-ldl dmd testclass.d -fPIC -shared
Jul 18 2012
Probably you mean the same problem that is described in the thread avobe, see "using GC needs particular skills?" Every time after execution my code I got very frustating access violation and the problem was misunderstanding garbage collector because I've never used it before.
Jul 18 2012