www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - How to create a shared library with DMD on Linux?

reply Bradley Smith <digitalmars-com baysmith.com> writes:
I'm experimenting with using D for Java Native Interface (JNI) 
programming. Although DMD 1.0 appears to support shared objects on 
Linux, I can't figure out how to create a shared library which can be 
used by a non-D program (in this case java).

Is it possible to create a shared library with DMD which can be used by 
a C program?

If I try to create the shared library with dmd, I get an error on the 
symbol _d_throw 4.

 dmd -fPIC nativetest.d jni.d jni_md.d -oflibnativetest.so -L-shared
gcc nativetest.o jni.o jni_md.o -o libnativetest.so -m32 -lphobos -lpthread -lm -Xlinker -shared -Xlinker -L/home/basmith/tools/dmd/dmd/lib /usr/bin/ld: libnativetest.so: undefined versioned symbol name _d_throw 4 /usr/bin/ld: failed to set dynamic section sizes: Bad value collect2: ld returned 1 exit status If I create shared objects with -fPIC and then create a shared library with gcc, the library is missing symbols from phobos.
 dmd -c -fPIC nativetest.d jni.d jni_md.d
 gcc nativetest.o jni.o jni_md.o -o libnativetest.so -shared
 java -Djava.library.path=. nativetest
Exception in thread "main" java.lang.UnsatisfiedLinkError: /home/basmith/programming/d/djni/libnativetest.so: /home/basmith/programming/d/djni/libnativetest.so: undefined symbol: _Dmodule_ref at java.lang.ClassLoader$NativeLibrary.load(Native Method) at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1751) at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1676) at java.lang.Runtime.loadLibrary0(Runtime.java:822) at java.lang.System.loadLibrary(System.java:993) at nativetest.<clinit>(nativetest.java:4) The full code and a build.sh script are in the attached tar.gz file. Thanks, Bradley
Jan 09 2007
parent reply Heinz <billgates microsoft.com> writes:
Hi,

You can't create shared libraries for unix with DMD, it's written somewhere
around
the website (i remerber it says that Walter haven't figured about library
structure or implementation or something under unix, it's on the todo list).

BUT, i think GDC can do it: http://dgcc.sourceforge.net/

Good luck
Jan 09 2007
next sibling parent reply rochus <rochus rochus.net> writes:
Heinz wrote:
 Hi,
 
 You can't create shared libraries for unix with DMD, it's written somewhere
around
 the website (i remerber it says that Walter haven't figured about library
 structure or implementation or something under unix, it's on the todo list).
 
 BUT, i think GDC can do it: http://dgcc.sourceforge.net/
 
 Good luck
Hi Heinz, It _is_ possible to write shared objects for unix using DMD. What does not work is linking against this shared object using another language than D. best regards, nicolai
Jan 10 2007
parent reply Bradley Smith <digitalmars-com baysmith.com> writes:
I was hoping that I was doing something wrong and it could be linked 
against a non-D language.

Thanks,
   Bradley

rochus wrote:
 Heinz wrote:
 Hi,

 You can't create shared libraries for unix with DMD, it's written somewhere
around
 the website (i remerber it says that Walter haven't figured about library
 structure or implementation or something under unix, it's on the todo list).

 BUT, i think GDC can do it: http://dgcc.sourceforge.net/

 Good luck
Hi Heinz, It _is_ possible to write shared objects for unix using DMD. What does not work is linking against this shared object using another language than D. best regards, nicolai
Jan 10 2007
parent reply rochus <rochus rochus.net> writes:
Bradley Smith wrote:
 I was hoping that I was doing something wrong and it could be linked
 against a non-D language.
 
 Thanks,
   Bradley
Hi Bradly, Good news! The topic won't let me sleep and i figured out how to create a shared object that may be accessed from an application written in plain C, so i guess it might work for your JNI-problem, too. The "magic" thing to add is: Instead of simply "exporting" your functions in your library, place them within an "extern (C)"-Block: extern (C) { int myFunction(int i) { doSomething; return somethingElse; } } I attached my sample layout, a library that has one function called "squareIt" (guess what it does *g*). There are three directories: app_c, app_d and lib, each containing a Makefile. They should be self explaining as there's not much in them. Important though: i called dmd with the argument "-fPIC" when compiling the library, though I don't think that this switch is recognized - it's just there to remind myself that it's PIC we're gonna create. So here's what you should do: compile the library: #cd lib #make copy the library to a place, where ld might find it. for example /usr/lib or /usr/local/lib or temporarily alter the LD_LIBRARY_PATH var to /where/you/extracted/the/sample/lib/bin compile the sample applications: #cd app_d #make #cd app_c #make Run the applications. They worked for me. good luck, Nicolai
Jan 10 2007
parent reply Bradley Smith <digitalmars-com baysmith.com> writes:
Yes, your example works, but when I start using the standard library 
things don't work.

Suppose I want to create a debugging version of a library with simple 
print statement.

     int squareIt(int i)
     {
	writefln("squareIt ", i);
	return i*i;
     }

The app_d will now crash, and the app_c will not link because 
std.stdio.writefln is not defined. For app_c, if I add -lphobos -lm 
-lpthread, it still has unresolved references in deh2.o.

I also tried to add phobos/internal/deh2.d to the libsquare.so, but that 
  gives an unresolved symbol _d_throw 4.

Any other ideas?

Thanks,
   Bradley


rochus wrote:
 Bradley Smith wrote:
 I was hoping that I was doing something wrong and it could be linked
 against a non-D language.

 Thanks,
   Bradley
Hi Bradly, Good news! The topic won't let me sleep and i figured out how to create a shared object that may be accessed from an application written in plain C, so i guess it might work for your JNI-problem, too. The "magic" thing to add is: Instead of simply "exporting" your functions in your library, place them within an "extern (C)"-Block: extern (C) { int myFunction(int i) { doSomething; return somethingElse; } } I attached my sample layout, a library that has one function called "squareIt" (guess what it does *g*). There are three directories: app_c, app_d and lib, each containing a Makefile. They should be self explaining as there's not much in them. Important though: i called dmd with the argument "-fPIC" when compiling the library, though I don't think that this switch is recognized - it's just there to remind myself that it's PIC we're gonna create. So here's what you should do: compile the library: #cd lib #make copy the library to a place, where ld might find it. for example /usr/lib or /usr/local/lib or temporarily alter the LD_LIBRARY_PATH var to /where/you/extracted/the/sample/lib/bin compile the sample applications: #cd app_d #make #cd app_c #make Run the applications. They worked for me. good luck, Nicolai
Jan 10 2007
parent rochus <rochus rochus.net> writes:
Hi Bradley and sorry for the late answer, I couldn't afford to post
earlier because the university required all my attention.

I tried it with different ways, but it won't work. I guess the problem
is that the phobos' functions don't expose themselves as extern(C) (the
way I proposed doing it).

Nicolai
Jan 12 2007
prev sibling parent Bradley Smith <digitalmars-com baysmith.com> writes:
I can confirm that GDC 0.21 can do it.

Thanks,
   Bradley

Heinz wrote:
 Hi,
 
 You can't create shared libraries for unix with DMD, it's written somewhere
around
 the website (i remerber it says that Walter haven't figured about library
 structure or implementation or something under unix, it's on the todo list).
 
 BUT, i think GDC can do it: http://dgcc.sourceforge.net/
 
 Good luck
Jan 10 2007