Dynamic loading, D all the way (dmd 64bit 2.060/Ubuntu 64bit 12.04/x86_64)

Paulo Pinto pjmlp at progtools.org
Mon Aug 20 04:38:06 PDT 2012


On Monday, 20 August 2012 at 07:26:40 UTC, Jacob Carlborg wrote:
> On 2012-08-20 05:40, Carl Sturtivant wrote:
>> (By dynamic loading I mean using something like the C library 
>> function
>> dlopen to explicitly load a shared object at runtime. I do not 
>> mean
>> dynamic linking in the usual passive sense.)
>>
>> I just successfully got working a toy example of dynamically 
>> loading
>> (from a D program) a D shared object and then finding and 
>> calling
>> functions defined in the shared object, and not just with C 
>> linkage.
>>
>> The main program, main.d, was compiled and linked somewhat 
>> normally,
>> except for passing the linker via gcc the flags necessary to 
>> ensure that
>> the whole of libphobos2.a is present and that all symbols in 
>> the
>> resulting executable are exposed dynamically.
>>
>> The shared object source, dload.d was compiled to an object 
>> file
>> containing position independent code by dmd. Then I invoked 
>> the linker
>> explicitly and had it make a shared object without the D 
>> runtime system
>> or Phobos. This is the novel step, and it enables the shared 
>> object to
>> resolve its linkage to the D runtime system and Phobos at the 
>> point of
>> being loaded, via callbacks to the main program. Thus the 
>> troubles of D
>> in shared objects are largely circumvented. There is only one 
>> instance
>> of phobos and D-runtime, in the main program. (Once phobos and 
>> druntime
>> are shared objects in the future somewhere this will work with 
>> no code
>> bloat.)
>>
>> The static initialization code in dload.d is automatically 
>> executed when
>> the shared object libdload.so is loaded by the main program, 
>> because the
>> linker is also passed a flag indicating the static 
>> initialization
>> block's mangled name, dynamically determined from dload.o 
>> before linkage
>> to libdload.so occurs.
>>
>> Finally, the mangled names of the functions to load are 
>> determined by a
>> call of a function with C linkage in dload.d from main.d that 
>> looks up
>> those names in an associative array initialized in the static
>> initialization block of dload.d where those mangled names are 
>> directly
>> available, so that full D linkage can be emulated, at least 
>> for functions.
>>
>> One thing: the garbage collector needs to be aware of static 
>> and
>> 'global' D variables in the shared object. Can a technical 
>> expert verify
>> that I've done the right thing to achieve that happy state of 
>> affairs in
>> this unusual context?
>>
>> So, what's overlooked here? I know that the static 
>> initialization code
>> cannot successfully throw an exception. Yet if a function in 
>> the shared
>> object is called from the main program and throws an 
>> exception, all is
>> well. (Try these.) See my comments in dload.d about this. What 
>> is it
>> about the implementation of exceptions that's problematic here?
>>
>> All files attached, including a Makefile with the exact 
>> options passed
>> to dmd, gcc and ld.
>
> I'm not sure I'm following what you exactly have done here but 
> in general this is what needs to be done to make dynamic 
> libraries properly work in D :
>
> * Initialize module infos (module constructors and similar)
> * Add TLS variables
> * Add exception handling tables
> * Add GC roots
>
> The above four things need to be extracted from the loaded 
> dynamic library and it gets loaded and preferably remove them 
> as well when the dynamic library gets unloaded. Currently this 
> is only extracted from the running executable. This is platform 
> dependent but usually it's extracted using bracketed sections 
> via extern C variables.

Should this be made automatically by the compiler?

This would be my expectation based on my experience with dynamic 
libraries in Turbo Pascal/Delphi.

--
Paulo



More information about the Digitalmars-d mailing list