View mode: basic / threaded / horizontal-split · Log in · Help
April 08, 2012
Shared library in D on Linux
I am still testing which setup gives me reliable shared D 
libraries which can be used from C.

Here is my latest test:

* test.d:
import std.stdio;
extern (C) {
  void hiD() {
    writeln("hi from D lib");
  }
}

* main.c
#include <stdio.h>
#include <dlfcn.h>
#include <stdlib.h>
void main() {
    void (*hiD)(void);
    void* handle = dlopen("./libtest.so", RTLD_LAZY);
    if (handle == NULL) {
        printf("%s\n", dlerror());
        exit(1);
    }	
    hiD = dlsym(handle, "hiD");
    if (hiD != NULL) {
        hiD();
    } else {
        printf("hiD is null\n");
    }
    dlclose(handle);
}

* Makefile
#!/bin/bash
test:
	#gdc-4.6 -g -c test.d -fPIC -o test.o
	#gdc-4.6 -shared -o libtest.so -fPIC test.o -lc -nostartfiles
	dmd -g -c test.d -fPIC
	ld -shared -o libtest.so test.o -lrt -lphobos2 -lpthread
	gcc -g main.c -ldl -lpthread
	./a.out
clean:
	rm -rf *.so *.o *.out

With this setup I get

  ./libtest.so: undefined symbol: _deh_beg

With a fake main method added I get

  make: *** [test] Segmentation fault

This is what I get from gdb

  Program received signal SIGSEGV, Segmentation fault.
  0xb7fd1ed3 in std.stdio.__T7writelnTAyaZ.writeln() 
(_param_0=...) at   /usr/include/d/dmd/phobos/std/stdio.d:1550
  1550	    enforce(fprintf(.stdout.p.handle, "%.*s\n",

Event with the following startup hooks

extern(C) {

  void gc_init();
  void gc_term();

  void _init() {
    gc_init();
  }

  void _fini() {
    gc_term();
  }

}

I get the same error. I am using dmd 2.058 on Ubuntu 11.10 (32 
bit)

With gdc I get different errors, but it seems even more difficult 
to get it working.

Does anyone know what is missing to get proper shared library 
support working on Linux?
April 08, 2012
Re: Shared library in D on Linux
On 2012-04-08 10:45, "Timo Westkämper" <timo.westkamper@gmail.com>" wrote:
> I am still testing which setup gives me reliable shared D libraries
> which can be used from C.
>
> Here is my latest test:
>
> * test.d:
> import std.stdio;
> extern (C) {
> void hiD() {
> writeln("hi from D lib");
> }
> }
>
> * main.c
> #include <stdio.h>
> #include <dlfcn.h>
> #include <stdlib.h>
> void main() {
> void (*hiD)(void);
> void* handle = dlopen("./libtest.so", RTLD_LAZY);
> if (handle == NULL) {
> printf("%s\n", dlerror());
> exit(1);
> }
> hiD = dlsym(handle, "hiD");
> if (hiD != NULL) {
> hiD();
> } else {
> printf("hiD is null\n");
> }
> dlclose(handle);
> }
>
> * Makefile
> #!/bin/bash
> test:
> #gdc-4.6 -g -c test.d -fPIC -o test.o
> #gdc-4.6 -shared -o libtest.so -fPIC test.o -lc -nostartfiles
> dmd -g -c test.d -fPIC
> ld -shared -o libtest.so test.o -lrt -lphobos2 -lpthread
> gcc -g main.c -ldl -lpthread
> ./a.out
> clean:
> rm -rf *.so *.o *.out
>
> With this setup I get
>
> ./libtest.so: undefined symbol: _deh_beg
>
> With a fake main method added I get
>
> make: *** [test] Segmentation fault
>
> This is what I get from gdb
>
> Program received signal SIGSEGV, Segmentation fault.
> 0xb7fd1ed3 in std.stdio.__T7writelnTAyaZ.writeln() (_param_0=...) at
> /usr/include/d/dmd/phobos/std/stdio.d:1550
> 1550 enforce(fprintf(.stdout.p.handle, "%.*s\n",
>
> Event with the following startup hooks
>
> extern(C) {
>
> void gc_init();
> void gc_term();
>
> void _init() {
> gc_init();
> }
>
> void _fini() {
> gc_term();
> }
>
> }
>
> I get the same error. I am using dmd 2.058 on Ubuntu 11.10 (32 bit)
>
> With gdc I get different errors, but it seems even more difficult to get
> it working.
>
> Does anyone know what is missing to get proper shared library support
> working on Linux?

This is what I can think of for now:

* Proper initialization of TLS data
* Setting up exception handling tables
* Setting up module info

-- 
/Jacob Carlborg
April 08, 2012
Re: Shared library in D on Linux
On 04/08/2012 03:45 AM, "Timo Westkämper" <timo.westkamper@gmail.com>" 
wrote:
>
> extern(C) {
>
> void gc_init();
> void gc_term();
>
> void _init() {
> gc_init();
> }
>
> void _fini() {
> gc_term();
> }
>
> }

I think you want rt_init and rt_term here.
April 08, 2012
Re: Shared library in D on Linux
I'm interessting in the same stuff. I've a question to _tlsend and
_tlsstart. What are they used for? My disputable presumption was that
they point to the begin of TLS segment.


What is _deh_begin and _deh_end used for?
April 08, 2012
Re: Shared library in D on Linux
On Sunday, 8 April 2012 at 14:52:55 UTC, Ellery Newcomer wrote:
> On 04/08/2012 03:45 AM, "Timo Westkämper" 
> <timo.westkamper@gmail.com>" wrote:
>>
>> extern(C) {
>>
>> void gc_init();
>> void gc_term();
>>
>> void _init() {
>> gc_init();
>> }
>>
>> void _fini() {
>> gc_term();
>> }
>>
>> }
>
> I think you want rt_init and rt_term here.

I got now the simple example working:

* Makefile:
#!/bin/bash
test:
	dmd -lib -g -c test.d -fPIC
	ld -shared -o libtest.so test.a -lrt -lphobos2 -lpthread
	gcc -g main.c -ldl -lpthread
	./a.out
clean:
	rm -rf *.a *.so *.o *.out

* test.d:
import std.stdio;
extern (C) void hiD() {
  writeln("hi from D lib");
}

Compiling as lib did the track and added the missing parts.

I will now advance with more complex examples.
April 08, 2012
Re: Shared library in D on Linux
On 2012-04-08 17:53, mta`chrono wrote:
> I'm interessting in the same stuff. I've a question to _tlsend and
> _tlsstart. What are they used for? My disputable presumption was that
> they point to the begin of TLS segment.

Yes, exactly, the start and end of the TLS segment.

> What is _deh_begin and _deh_end used for?

That would be start and end of the segment containing the exception 
handling tables.

-- 
/Jacob Carlborg
April 08, 2012
Re: Shared library in D on Linux
Does someone know why the lib (.a) packaging instead of objects 
(.o) works better in this case?
April 09, 2012
Re: Shared library in D on Linux
On Sunday, 8 April 2012 at 17:59:28 UTC, Timo Westkämper wrote:
> Does someone know why the lib (.a) packaging instead of objects 
> (.o) works better in this case?

Didn't work after all with -lib. I mixed up outputs.
April 09, 2012
Re: Shared library in D on Linux
Well, if you're really hankering for a shared lib, try ldc. I have 
gotten it to compile working shared libs in the past.

On 04/09/2012 01:24 AM, "Timo Westkämper" <timo.westkamper@gmail.com>" 
wrote:
> On Sunday, 8 April 2012 at 17:59:28 UTC, Timo Westkämper wrote:
>> Does someone know why the lib (.a) packaging instead of objects (.o)
>> works better in this case?
>
> Didn't work after all with -lib. I mixed up outputs.
April 09, 2012
Re: Shared library in D on Linux
On Monday, 9 April 2012 at 15:14:45 UTC, Ellery Newcomer wrote:
> Well, if you're really hankering for a shared lib, try ldc. I 
> have gotten it to compile working shared libs in the past.
>
> On 04/09/2012 01:24 AM, "Timo Westkämper" 
> <timo.westkamper@gmail.com>" wrote:
>> On Sunday, 8 April 2012 at 17:59:28 UTC, Timo Westkämper 
>> wrote:
>>> Does someone know why the lib (.a) packaging instead of 
>>> objects (.o)
>>> works better in this case?
>>
>> Didn't work after all with -lib. I mixed up outputs.

Thanks, I might switch to ldc, if dmd and gdc fail here.

I found this tls.S script in the druntime sources (src/rt/tls.S). 
Do you think it could be included in the library to make tls 
initialization work?

#if linux

/* The memory between the addresses of _tlsstart and _tlsend is 
the storage for
 * thread-local data in D 2.0.  Both of these rely on the default 
linker script
 * of:
 *      .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) }
 *      .tbss  : { *(.tbss .tbss.* .gnu.linkonce.tb.*) 
*(.tcommon) }
 * to group the sections in that order.
 *
 * Sadly, this does not work because ld orders .tdata after 
.tdata.*, despite
 * what the linker script says.
 */

.file "tls.S"

.globl _tlsstart
    .section .tdata,"awT",@progbits
    .align 4
    .type   _tlsstart, @object
    .size   _tlsstart, 4
_tlsstart:
    .long   3

.globl _tlsend
    .section .tcommon,"awT",@nobits
    .align 4
    .type   _tlsend, @object
    .size   _tlsend, 4
_tlsend:
    .zero   4

#endif


I will see if I can copy the exception handling parts from the D 
main wrapping code.

As a temporary solution I did this

extern(C) void _deh_beg() { }
extern(C) void _deh_end() { }
« First   ‹ Prev
1 2 3
Top | Discussion index | About this forum | D home