www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Libraries, users, DLLs

reply "antiAlias" <gblazzer corneleus.com> writes:
Currently, D libraries are predominantly linked in a static fashion. I have
a fairly substantial OO library that I'd really like to distribute as a
dll/shared-lib, but there are apparently a number of issues that stop one
doing so. I may have all of this completely wrong, and I'm really looking
for guidance more that anything else:

1) each DLL has its own GC. Crossing DLL boundaries is a problem for memory
allocations, especially for OO libraries (new doesn't work; some methods
allocate within the DLL but the reference is held by the client instead;
etc).

2) as I understand it, Exceptions do not cross DLL boundaries correctly

One of the goals of providing a library is "ease of use" for the end user. I
don't wish to make anyone jump through hoops just to use an OO class from a
DLL, yet the library really needs to be shareable (there's potentially a
very large number of small bound clients, so one would hope to avoid
static-binding where possible). Can someone point me in the right direction?
Or can we get some support from the compiler, if it's necessary? After all,
a new language is a tough sell without good, easy to use libraries ...
right?
Aug 08 2004
parent reply Lars Ivar Igesund <larsivar igesund.net> writes:
antiAlias wrote:

 Currently, D libraries are predominantly linked in a static fashion. I have
 a fairly substantial OO library that I'd really like to distribute as a
 dll/shared-lib, but there are apparently a number of issues that stop one
 doing so. I may have all of this completely wrong, and I'm really looking
 for guidance more that anything else:
 
 1) each DLL has its own GC. Crossing DLL boundaries is a problem for memory
 allocations, especially for OO libraries (new doesn't work; some methods
 allocate within the DLL but the reference is held by the client instead;
 etc).
 
 2) as I understand it, Exceptions do not cross DLL boundaries correctly
 
 One of the goals of providing a library is "ease of use" for the end user. I
 don't wish to make anyone jump through hoops just to use an OO class from a
 DLL, yet the library really needs to be shareable (there's potentially a
 very large number of small bound clients, so one would hope to avoid
 static-binding where possible). Can someone point me in the right direction?
 Or can we get some support from the compiler, if it's necessary? After all,
 a new language is a tough sell without good, easy to use libraries ...
 right?
 
 

I have to say that I agree. DLL's are supposed to be the glorious way forward (at least it is what is preached outside the D world), but being rather difficult to use correctly and safely seems to keep most people from actually creating any. At the very least, strategies for how to overcome the problems mentioned above, should be collected (at the Wiki, I suppose). Maybe it's possible to make tools that can create the factories, stubs, etc automatically, but it sure would be nice to be able to use them the easy way. I would like to come with suggestions for how to 'fix' the DLL's, but I don't think I really have the know-how to even suggest. I *do* know though, that I would like to not have to use reference-counting. Lars Ivar Igesund
Aug 09 2004
next sibling parent "Matthew" <admin.hat stlsoft.dot.org> writes:
"Lars Ivar Igesund" <larsivar igesund.net> wrote in message
news:cf73n3$b1l$2 digitaldaemon.com...
 antiAlias wrote:

 Currently, D libraries are predominantly linked in a static fashion. I have
 a fairly substantial OO library that I'd really like to distribute as a
 dll/shared-lib, but there are apparently a number of issues that stop one
 doing so. I may have all of this completely wrong, and I'm really looking
 for guidance more that anything else:

 1) each DLL has its own GC. Crossing DLL boundaries is a problem for memory
 allocations, especially for OO libraries (new doesn't work; some methods
 allocate within the DLL but the reference is held by the client instead;
 etc).

 2) as I understand it, Exceptions do not cross DLL boundaries correctly

 One of the goals of providing a library is "ease of use" for the end user. I
 don't wish to make anyone jump through hoops just to use an OO class from a
 DLL, yet the library really needs to be shareable (there's potentially a
 very large number of small bound clients, so one would hope to avoid
 static-binding where possible). Can someone point me in the right direction?
 Or can we get some support from the compiler, if it's necessary? After all,
 a new language is a tough sell without good, easy to use libraries ...
 right?

I have to say that I agree. DLL's are supposed to be the glorious way forward (at least it is what is preached outside the D world), but being rather difficult to use correctly and safely seems to keep most people from actually creating any. At the very least, strategies for how to overcome the problems mentioned above, should be collected (at the Wiki, I suppose). Maybe it's possible to make tools that can create the factories, stubs, etc automatically, but it sure would be nice to be able to use them the easy way. I would like to come with suggestions for how to 'fix' the DLL's, but I don't think I really have the know-how to even suggest. I *do* know though, that I would like to not have to use reference-counting. Lars Ivar Igesund

If someone could right a brief - 2 page? - treatise on the current state, and their perceived problems, I'd be happy to take a look at start to digest the problem.
Aug 08 2004
prev sibling parent reply pragma <EricAnderton at yahoo dot com> <pragma_member pathlink.com> writes:
In article <cf73n3$b1l$2 digitaldaemon.com>, Lars Ivar Igesund says...
antiAlias wrote:

 Currently, D libraries are predominantly linked in a static fashion. I have
 a fairly substantial OO library that I'd really like to distribute as a
 dll/shared-lib, but there are apparently a number of issues that stop one
 doing so. I may have all of this completely wrong, and I'm really looking
 for guidance more that anything else:
 
 1) each DLL has its own GC. Crossing DLL boundaries is a problem for memory
 allocations, especially for OO libraries (new doesn't work; some methods
 allocate within the DLL but the reference is held by the client instead;
 etc).
 
 2) as I understand it, Exceptions do not cross DLL boundaries correctly
 
 One of the goals of providing a library is "ease of use" for the end user. I
 don't wish to make anyone jump through hoops just to use an OO class from a
 DLL, yet the library really needs to be shareable (there's potentially a
 very large number of small bound clients, so one would hope to avoid
 static-binding where possible). Can someone point me in the right direction?
 Or can we get some support from the compiler, if it's necessary? After all,
 a new language is a tough sell without good, easy to use libraries ...
 right?
 
 

I have to say that I agree. DLL's are supposed to be the glorious way forward (at least it is what is preached outside the D world), but being rather difficult to use correctly and safely seems to keep most people from actually creating any. At the very least, strategies for how to overcome the problems mentioned above, should be collected (at the Wiki, I suppose). Maybe it's possible to make tools that can create the factories, stubs, etc automatically, but it sure would be nice to be able to use them the easy way. I would like to come with suggestions for how to 'fix' the DLL's, but I don't think I really have the know-how to even suggest. I *do* know though, that I would like to not have to use reference-counting. Lars Ivar Igesund

Honestly, I've already surmounted a huge number of issues regarding D DLL's in my time writing DSP. I've had to devise some workarounds including, but not limited to: object proxies, pointer lists and event messaging to signal dll unloads. I like your suggestion that solutions should be up on the Wiki, and I may publish my findings there. :) Like everyone in this thread, I want more from D with regard to how libraries are handled. Here's my $0.02: What is really missing is giving the DLL's a larger role in the eyes of the garbage collector. Having a separate GC on each library works well when having D inter-operate with different languages, but within a 100% D project it can become a hinderance. Without close and careful management of where a given D object "lives", releasing a DLL mid-process can be disasterous. However, this isn't any different from what we've already come to know about C and C++, its just something we would all rather live without (what with D already making strides to overcome other problems in C++). Two years ago, I put down development of my own GC-based runtime library for C++ I came across this issue and devised some solutions for it, but was unable to implement it as my GC engine had some impossible-to-debug quirks with it. For all that effort, I did learn some rather invaluable lessons about the impact a collector has on a language. Hooking a GC into another dll isn't that hard to do, as long as one is willing to take on the notion of D-platform-dependent libraries. Ultimately, I realized that the problem regarding Dll's and GC engines is easy provided you can answer one question: Does a given pointer represent a pointer to code on a given DLL, or to a valid root in a given DLL? From this we can deduce the rest of the information we need to do everything else dynamically. If a DLL has no vtables or delegates pointing to it's code, and no pointers elsewhere to any other roots within the DLL, then there are no dependencies on that DLL and it may be dismissed. This leads up to the notion that DLL's themselves may be managed by utilizing the gc. A DLL can be treated as a collectable object, provided that its root pointers and _entire code space_ are set as roots to be scanned by the hosting process's garbage collector. Such A DLL can be unloaded from the process in a manner analagous to collection of a typical object (i.e. lazy destruction and release of resources). The result is something that is almost totally transparent to the language, provided that phobos is given some additional support (outside of std.loader) for DLLs. Careful object management and prodding the GC should be enough to get a library to release/unload/close whenever needed. By constrast an explicit and immediate unload of a DLL requires far more plumbing and participation on behalf of the library developer and library user alike. Collectable DLL's, IMO are the way forward for D. - Pragma
Aug 09 2004
parent reply "antiAlias" <fu bar.com> writes:
What you suggest sounds really promising Eric, and it would certainly help
tremendously with what I'm doing.

So, what am I doing, specifically? Well, Mango has a clustering package,
used for the caching, queuing, and execution of D classes across a LAN.
Naturally, the classes passed around at runtime must be known at
compile-time.

Within a cluster, the server (storage) nodes get around this problem by
maintaining such classes in serialized form only. That is, they deliberately
avoid instantiating an instance (otherwise they'd need to be compiled with
every single possible class that might be stored).

The cluster-clients, on the other hand, do need to know about each class ~
since they will receive and operate upon concrete class instances. These
classes must be known at compile time. For certain applications this is not
a restriction of any kind. In fact, it may actually be viewed as security
benefit.

However, most software systems evolve rather dynamically, and rebooting an
entire operational network to get some new class-instances configured into
the cluster is just not practical.

That's where DLL's (or shared libs) step in. In particular, the clustering
package would benefit greatly if the mobile classes involved were packaged
as discrete dll's. That way, it would be easy to ship them around the
cluster too (as files), and they'd 'attach' to client nodes as appropriate.
This is very similar in approach to how servlets are loaded dynamically into
a running server (and reloaded when they are seen to change).

The other factor involved in such an approach is this: these mobile classes
often need to use resources outside of their own codebase (think Mango
classes, or a database, or whatever). One does not want to bloat the mobile
dll's with such artifacts ~ they should be bound when said dll is loaded
instead. That is, the Mango library itself should be a dll.

Being able to do this cleanly, elegantly, efficiently, and robustly is
important. I think something needs to be done to bring D up-to-date in this
respect.

How about it?




"pragma" <EricAnderton at yahoo dot compragma_member pathlink.com> wrote in
message news:cf80ak$m3v$1 digitaldaemon.com...
 In article <cf73n3$b1l$2 digitaldaemon.com>, Lars Ivar Igesund says...
antiAlias wrote:

 Currently, D libraries are predominantly linked in a static fashion. I



 a fairly substantial OO library that I'd really like to distribute as a
 dll/shared-lib, but there are apparently a number of issues that stop



 doing so. I may have all of this completely wrong, and I'm really



 for guidance more that anything else:

 1) each DLL has its own GC. Crossing DLL boundaries is a problem for



 allocations, especially for OO libraries (new doesn't work; some



 allocate within the DLL but the reference is held by the client



 etc).

 2) as I understand it, Exceptions do not cross DLL boundaries correctly

 One of the goals of providing a library is "ease of use" for the end



 don't wish to make anyone jump through hoops just to use an OO class



 DLL, yet the library really needs to be shareable (there's potentially



 very large number of small bound clients, so one would hope to avoid
 static-binding where possible). Can someone point me in the right



 Or can we get some support from the compiler, if it's necessary? After



 a new language is a tough sell without good, easy to use libraries ...
 right?

I have to say that I agree. DLL's are supposed to be the glorious way forward (at least it is what is preached outside the D world), but being rather difficult to use correctly and safely seems to keep most people from actually creating any. At the very least, strategies for how to overcome the problems mentioned above, should be collected (at the Wiki, I suppose). Maybe it's possible to make tools that can create the factories, stubs, etc automatically, but it sure would be nice to be able to use them the easy way. I would like to come with suggestions for how to 'fix' the DLL's, but I don't think I really have the know-how to even suggest. I *do* know though, that I would like to not have to use reference-counting. Lars Ivar Igesund

Honestly, I've already surmounted a huge number of issues regarding D

 my time writing DSP.  I've had to devise some workarounds including, but

 limited to: object proxies, pointer lists and event messaging to signal

 unloads.  I like your suggestion that solutions should be up on the Wiki,

 may publish my findings there. :)  Like everyone in this thread, I want

 from D with regard to how libraries are handled.

 Here's my $0.02:

 What is really missing is giving the DLL's a larger role in the eyes of

 garbage collector.  Having a separate GC on each library works well when

 D inter-operate with different languages, but within a 100% D project it

 become a hinderance.  Without close and careful management of where a

 object "lives", releasing a DLL mid-process can be disasterous.  However,

 isn't any different from what we've already come to know about C and C++,

 just something we would all rather live without (what with D already

 strides to overcome other problems in C++).

 Two years ago, I put down development of my own GC-based runtime library

   I came across this issue and devised some solutions for it, but was

 implement it as my GC engine had some impossible-to-debug quirks with it.

 all that effort, I did learn some rather invaluable lessons about the

 collector has on a language.

 Hooking a GC into another dll isn't that hard to do, as long as one is

 to take on the notion of D-platform-dependent libraries.  Ultimately, I

 that the problem regarding Dll's and GC engines is easy provided you can

 one question:

 Does a given pointer represent a pointer to code on a given DLL, or to a

 root in a given DLL?

 From this we can deduce the rest of the information we need to do

 else dynamically.  If a DLL has no vtables or delegates pointing to it's

 and no pointers elsewhere to any other roots within the DLL, then there

 dependencies on that DLL and it may be dismissed.  This leads up to the

 that DLL's themselves may be managed by utilizing the gc.

 A DLL can be treated as a collectable object, provided that its root

 and _entire code space_ are set as roots to be scanned by the hosting

 garbage collector.  Such A DLL can be unloaded from the process in a

 analagous to collection of a typical object (i.e. lazy destruction and

 of resources).

 The result is something that is almost totally transparent to the

 provided that phobos is given some additional support (outside of

 for DLLs.  Careful object management and prodding the GC should be enough

 a library to release/unload/close whenever needed.

 By constrast an explicit and immediate unload of a DLL requires far more
 plumbing and participation on behalf of the library developer and library

 alike.  Collectable DLL's, IMO are the way forward for D.

 - Pragma

Aug 19 2004
parent reply "Matthew" <admin.hat stlsoft.dot.org> writes:
Kris,

... cough ... splutter ...

sorry.

Mr Alias

From your description of your requirements I would say that it's _possible_
that you can implement what you need by
using interfaces, and being _very_ careful with your memory management, but I
don't fancy your (or anyone else's)
chances of making such an infrastructure simply, robustly and flexibly. For my
money, I don't think D's got any kind of
acceptable answer to this issue atm.

Nomenclatural definition: I use the term "link unit" a lot. I'm sure you'll
grok the full extent of the concept when I
say that an exes and dynamic libs are link-units, and static libs are not.
Another way to think of it is link units
define a complete symbol name space. (For more on this and other fascinating
issues, please feel free to preorder a copy
of "Imperfect C++" from
http://www.amazon.com/exec/obidos/tg/detail/-/0321228774/ <g>)

I see four issues with DLLs and D. I'm interested to hear whether I've missed
any and, especially, what ideas people
have for solving these issues in a "Spirit of D" way (i.e. without all the
clodhopping nonsense that is the Java/.NET
infrastructure):

1. Sharing/managing GC - I think this is the most important in the short/medium
term
2. Being able to talk _classes_ not just _interfaces_ between link units. We
can get a long way with interfaces,
methinks, once GC sharing is handled, but still it'd be nice to work with
classes as well, if simply achievable.
3. Versioning, i.e. avoiding DLL Hell
4. Security. Is there something simple and efficient that nonetheless addresses
those handled by the heaving leviathan
that is .NET?

Ancilary issues:

1. Serialisation as a part of the language??


(Germane) thoughts everyone?

Cheers



-- 
Matthew Wilson

Author: "Imperfect C++", Addison-Wesley, 2004
    (http://www.imperfectcplusplus.com)
Contributing editor, C/C++ Users Journal
    (http://www.synesis.com.au/articles.html#columns)
Director, Synesis Software
    (www.synesis.com.au)
STLSoft moderator
    (http://www.stlsoft.org)

"Youth ages, Immaturity is outgrown, Ignorance can be educated, drunkeness
sobered. But stupid lasts forever",
Aristophenes

-----------------------------------------------------





"antiAlias" <fu bar.com> wrote in message
news:cg3pmt$2q32$1 digitaldaemon.com...
 What you suggest sounds really promising Eric, and it would certainly help
 tremendously with what I'm doing.

 So, what am I doing, specifically? Well, Mango has a clustering package,
 used for the caching, queuing, and execution of D classes across a LAN.
 Naturally, the classes passed around at runtime must be known at
 compile-time.

 Within a cluster, the server (storage) nodes get around this problem by
 maintaining such classes in serialized form only. That is, they deliberately
 avoid instantiating an instance (otherwise they'd need to be compiled with
 every single possible class that might be stored).

 The cluster-clients, on the other hand, do need to know about each class ~
 since they will receive and operate upon concrete class instances. These
 classes must be known at compile time. For certain applications this is not
 a restriction of any kind. In fact, it may actually be viewed as security
 benefit.

 However, most software systems evolve rather dynamically, and rebooting an
 entire operational network to get some new class-instances configured into
 the cluster is just not practical.

 That's where DLL's (or shared libs) step in. In particular, the clustering
 package would benefit greatly if the mobile classes involved were packaged
 as discrete dll's. That way, it would be easy to ship them around the
 cluster too (as files), and they'd 'attach' to client nodes as appropriate.
 This is very similar in approach to how servlets are loaded dynamically into
 a running server (and reloaded when they are seen to change).

 The other factor involved in such an approach is this: these mobile classes
 often need to use resources outside of their own codebase (think Mango
 classes, or a database, or whatever). One does not want to bloat the mobile
 dll's with such artifacts ~ they should be bound when said dll is loaded
 instead. That is, the Mango library itself should be a dll.

 Being able to do this cleanly, elegantly, efficiently, and robustly is
 important. I think something needs to be done to bring D up-to-date in this
 respect.

 How about it?




 "pragma" <EricAnderton at yahoo dot compragma_member pathlink.com> wrote in
 message news:cf80ak$m3v$1 digitaldaemon.com...
 In article <cf73n3$b1l$2 digitaldaemon.com>, Lars Ivar Igesund says...
antiAlias wrote:

 Currently, D libraries are predominantly linked in a static fashion. I



 a fairly substantial OO library that I'd really like to distribute as a
 dll/shared-lib, but there are apparently a number of issues that stop



 doing so. I may have all of this completely wrong, and I'm really



 for guidance more that anything else:

 1) each DLL has its own GC. Crossing DLL boundaries is a problem for



 allocations, especially for OO libraries (new doesn't work; some



 allocate within the DLL but the reference is held by the client



 etc).

 2) as I understand it, Exceptions do not cross DLL boundaries correctly

 One of the goals of providing a library is "ease of use" for the end



 don't wish to make anyone jump through hoops just to use an OO class



 DLL, yet the library really needs to be shareable (there's potentially



 very large number of small bound clients, so one would hope to avoid
 static-binding where possible). Can someone point me in the right



 Or can we get some support from the compiler, if it's necessary? After



 a new language is a tough sell without good, easy to use libraries ...
 right?

I have to say that I agree. DLL's are supposed to be the glorious way forward (at least it is what is preached outside the D world), but being rather difficult to use correctly and safely seems to keep most people from actually creating any. At the very least, strategies for how to overcome the problems mentioned above, should be collected (at the Wiki, I suppose). Maybe it's possible to make tools that can create the factories, stubs, etc automatically, but it sure would be nice to be able to use them the easy way. I would like to come with suggestions for how to 'fix' the DLL's, but I don't think I really have the know-how to even suggest. I *do* know though, that I would like to not have to use reference-counting. Lars Ivar Igesund

Honestly, I've already surmounted a huge number of issues regarding D

 my time writing DSP.  I've had to devise some workarounds including, but

 limited to: object proxies, pointer lists and event messaging to signal

 unloads.  I like your suggestion that solutions should be up on the Wiki,

 may publish my findings there. :)  Like everyone in this thread, I want

 from D with regard to how libraries are handled.

 Here's my $0.02:

 What is really missing is giving the DLL's a larger role in the eyes of

 garbage collector.  Having a separate GC on each library works well when

 D inter-operate with different languages, but within a 100% D project it

 become a hinderance.  Without close and careful management of where a

 object "lives", releasing a DLL mid-process can be disasterous.  However,

 isn't any different from what we've already come to know about C and C++,

 just something we would all rather live without (what with D already

 strides to overcome other problems in C++).

 Two years ago, I put down development of my own GC-based runtime library

   I came across this issue and devised some solutions for it, but was

 implement it as my GC engine had some impossible-to-debug quirks with it.

 all that effort, I did learn some rather invaluable lessons about the

 collector has on a language.

 Hooking a GC into another dll isn't that hard to do, as long as one is

 to take on the notion of D-platform-dependent libraries.  Ultimately, I

 that the problem regarding Dll's and GC engines is easy provided you can

 one question:

 Does a given pointer represent a pointer to code on a given DLL, or to a

 root in a given DLL?

 From this we can deduce the rest of the information we need to do

 else dynamically.  If a DLL has no vtables or delegates pointing to it's

 and no pointers elsewhere to any other roots within the DLL, then there

 dependencies on that DLL and it may be dismissed.  This leads up to the

 that DLL's themselves may be managed by utilizing the gc.

 A DLL can be treated as a collectable object, provided that its root

 and _entire code space_ are set as roots to be scanned by the hosting

 garbage collector.  Such A DLL can be unloaded from the process in a

 analagous to collection of a typical object (i.e. lazy destruction and

 of resources).

 The result is something that is almost totally transparent to the

 provided that phobos is given some additional support (outside of

 for DLLs.  Careful object management and prodding the GC should be enough

 a library to release/unload/close whenever needed.

 By constrast an explicit and immediate unload of a DLL requires far more
 plumbing and participation on behalf of the library developer and library

 alike.  Collectable DLL's, IMO are the way forward for D.

 - Pragma


Aug 19 2004
parent reply "antiAlias" <fu bar.com> writes:
I agree that #1 (the shared GC) is a primary issue. On the face of it, what
Eric describes (below) sounds really attractive.

Other than that, what about the exception-boundary issue?



"Matthew" <admin.hat stlsoft.dot.org> wrote in message
news:cg3ul4$2sq0$1 digitaldaemon.com...
 Kris,

 ... cough ... splutter ...

 sorry.

 Mr Alias

 From your description of your requirements I would say that it's

 using interfaces, and being _very_ careful with your memory management,

 chances of making such an infrastructure simply, robustly and flexibly.

 acceptable answer to this issue atm.

 Nomenclatural definition: I use the term "link unit" a lot. I'm sure

 say that an exes and dynamic libs are link-units, and static libs are not.

 define a complete symbol name space. (For more on this and other

 of "Imperfect C++" from

 I see four issues with DLLs and D. I'm interested to hear whether I've

 have for solving these issues in a "Spirit of D" way (i.e. without all the

 infrastructure):

 1. Sharing/managing GC - I think this is the most important in the

 2. Being able to talk _classes_ not just _interfaces_ between link units.

 methinks, once GC sharing is handled, but still it'd be nice to work with

 3. Versioning, i.e. avoiding DLL Hell
 4. Security. Is there something simple and efficient that nonetheless

 that is .NET?

 Ancilary issues:

 1. Serialisation as a part of the language??


 (Germane) thoughts everyone?

 Cheers



 --
 Matthew Wilson

 Author: "Imperfect C++", Addison-Wesley, 2004
     (http://www.imperfectcplusplus.com)
 Contributing editor, C/C++ Users Journal
     (http://www.synesis.com.au/articles.html#columns)
 Director, Synesis Software
     (www.synesis.com.au)
 STLSoft moderator
     (http://www.stlsoft.org)

 "Youth ages, Immaturity is outgrown, Ignorance can be educated, drunkeness

 Aristophenes

 -----------------------------------------------------





 "antiAlias" <fu bar.com> wrote in message

 What you suggest sounds really promising Eric, and it would certainly


 tremendously with what I'm doing.

 So, what am I doing, specifically? Well, Mango has a clustering package,
 used for the caching, queuing, and execution of D classes across a LAN.
 Naturally, the classes passed around at runtime must be known at
 compile-time.

 Within a cluster, the server (storage) nodes get around this problem by
 maintaining such classes in serialized form only. That is, they


 avoid instantiating an instance (otherwise they'd need to be compiled


 every single possible class that might be stored).

 The cluster-clients, on the other hand, do need to know about each class


 since they will receive and operate upon concrete class instances. These
 classes must be known at compile time. For certain applications this is


 a restriction of any kind. In fact, it may actually be viewed as


 benefit.

 However, most software systems evolve rather dynamically, and rebooting


 entire operational network to get some new class-instances configured


 the cluster is just not practical.

 That's where DLL's (or shared libs) step in. In particular, the


 package would benefit greatly if the mobile classes involved were


 as discrete dll's. That way, it would be easy to ship them around the
 cluster too (as files), and they'd 'attach' to client nodes as


 This is very similar in approach to how servlets are loaded dynamically


 a running server (and reloaded when they are seen to change).

 The other factor involved in such an approach is this: these mobile


 often need to use resources outside of their own codebase (think Mango
 classes, or a database, or whatever). One does not want to bloat the


 dll's with such artifacts ~ they should be bound when said dll is loaded
 instead. That is, the Mango library itself should be a dll.

 Being able to do this cleanly, elegantly, efficiently, and robustly is
 important. I think something needs to be done to bring D up-to-date in


 respect.

 How about it?




 "pragma" <EricAnderton at yahoo dot compragma_member pathlink.com> wrote


 message news:cf80ak$m3v$1 digitaldaemon.com...
 In article <cf73n3$b1l$2 digitaldaemon.com>, Lars Ivar Igesund says...
antiAlias wrote:

 Currently, D libraries are predominantly linked in a static





 have
 a fairly substantial OO library that I'd really like to distribute





 dll/shared-lib, but there are apparently a number of issues that





 one
 doing so. I may have all of this completely wrong, and I'm really



 for guidance more that anything else:

 1) each DLL has its own GC. Crossing DLL boundaries is a problem





 memory
 allocations, especially for OO libraries (new doesn't work; some



 allocate within the DLL but the reference is held by the client



 etc).

 2) as I understand it, Exceptions do not cross DLL boundaries





 One of the goals of providing a library is "ease of use" for the





 user. I
 don't wish to make anyone jump through hoops just to use an OO





 from a
 DLL, yet the library really needs to be shareable (there's





 a
 very large number of small bound clients, so one would hope to





 static-binding where possible). Can someone point me in the right



 Or can we get some support from the compiler, if it's necessary?





 all,
 a new language is a tough sell without good, easy to use libraries





 right?

I have to say that I agree. DLL's are supposed to be the glorious way forward (at least it is what is preached outside the D world), but




rather difficult to use correctly and safely seems to keep most




from actually creating any.

At the very least, strategies for how to overcome the problems




above, should be collected (at the Wiki, I suppose). Maybe it's




to make tools that can create the factories, stubs, etc




but it sure would be nice to be able to use them the easy way.

I would like to come with suggestions for how to 'fix' the DLL's, but




don't think I really have the know-how to even suggest. I *do* know
though, that I would like to not have to use reference-counting.

Lars Ivar Igesund

Honestly, I've already surmounted a huge number of issues regarding D

 my time writing DSP.  I've had to devise some workarounds including,



 not
 limited to: object proxies, pointer lists and event messaging to



 dll
 unloads.  I like your suggestion that solutions should be up on the



 and I
 may publish my findings there. :)  Like everyone in this thread, I



 more
 from D with regard to how libraries are handled.

 Here's my $0.02:

 What is really missing is giving the DLL's a larger role in the eyes



 the
 garbage collector.  Having a separate GC on each library works well



 having
 D inter-operate with different languages, but within a 100% D project



 can
 become a hinderance.  Without close and careful management of where a

 object "lives", releasing a DLL mid-process can be disasterous.



 this
 isn't any different from what we've already come to know about C and



 its
 just something we would all rather live without (what with D already

 strides to overcome other problems in C++).

 Two years ago, I put down development of my own GC-based runtime



 for C++
   I came across this issue and devised some solutions for it, but was

 implement it as my GC engine had some impossible-to-debug quirks with



 For
 all that effort, I did learn some rather invaluable lessons about the

 collector has on a language.

 Hooking a GC into another dll isn't that hard to do, as long as one is

 to take on the notion of D-platform-dependent libraries.  Ultimately,



 realized
 that the problem regarding Dll's and GC engines is easy provided you



 answer
 one question:

 Does a given pointer represent a pointer to code on a given DLL, or to



 valid
 root in a given DLL?

 From this we can deduce the rest of the information we need to do

 else dynamically.  If a DLL has no vtables or delegates pointing to



 code,
 and no pointers elsewhere to any other roots within the DLL, then



 are no
 dependencies on that DLL and it may be dismissed.  This leads up to



 notion
 that DLL's themselves may be managed by utilizing the gc.

 A DLL can be treated as a collectable object, provided that its root

 and _entire code space_ are set as roots to be scanned by the hosting

 garbage collector.  Such A DLL can be unloaded from the process in a

 analagous to collection of a typical object (i.e. lazy destruction and

 of resources).

 The result is something that is almost totally transparent to the

 provided that phobos is given some additional support (outside of

 for DLLs.  Careful object management and prodding the GC should be



 to get
 a library to release/unload/close whenever needed.

 By constrast an explicit and immediate unload of a DLL requires far



 plumbing and participation on behalf of the library developer and



 user
 alike.  Collectable DLL's, IMO are the way forward for D.

 - Pragma



Aug 19 2004
parent reply "Matthew" <admin.hat stlsoft.dot.org> writes:
"antiAlias" <fu bar.com> wrote in message
news:cg408a$2tge$1 digitaldaemon.com...
 I agree that #1 (the shared GC) is a primary issue. On the face of it, what
 Eric describes (below) sounds really attractive.

It sounds promising. I'd like to hear more fine details, though. I'd also like to hear if his ideas would require changes to std.loader (as I'm itching for an excuse to rewrite that stillborn obscenity). I'd also like to hear Walter's opinions on the matter. I think this issue is of sufficient import to be a 1.0 prerequesite, don't you?
 Other than that, what about the exception-boundary issue?

Well, D's going to have an ABI, and since all exceptions are going to co-exist memorywise (when the GC's linearised/homogenised), what's the prob?
 "Matthew" <admin.hat stlsoft.dot.org> wrote in message
 news:cg3ul4$2sq0$1 digitaldaemon.com...
 Kris,

 ... cough ... splutter ...

 sorry.

 Mr Alias

 From your description of your requirements I would say that it's

 using interfaces, and being _very_ careful with your memory management,

 chances of making such an infrastructure simply, robustly and flexibly.

 acceptable answer to this issue atm.

 Nomenclatural definition: I use the term "link unit" a lot. I'm sure

 say that an exes and dynamic libs are link-units, and static libs are not.

 define a complete symbol name space. (For more on this and other

 of "Imperfect C++" from

 I see four issues with DLLs and D. I'm interested to hear whether I've

 have for solving these issues in a "Spirit of D" way (i.e. without all the

 infrastructure):

 1. Sharing/managing GC - I think this is the most important in the

 2. Being able to talk _classes_ not just _interfaces_ between link units.

 methinks, once GC sharing is handled, but still it'd be nice to work with

 3. Versioning, i.e. avoiding DLL Hell
 4. Security. Is there something simple and efficient that nonetheless

 that is .NET?

 Ancilary issues:

 1. Serialisation as a part of the language??


 (Germane) thoughts everyone?

 Cheers



 --
 Matthew Wilson

 Author: "Imperfect C++", Addison-Wesley, 2004
     (http://www.imperfectcplusplus.com)
 Contributing editor, C/C++ Users Journal
     (http://www.synesis.com.au/articles.html#columns)
 Director, Synesis Software
     (www.synesis.com.au)
 STLSoft moderator
     (http://www.stlsoft.org)

 "Youth ages, Immaturity is outgrown, Ignorance can be educated, drunkeness

 Aristophenes

 -----------------------------------------------------





 "antiAlias" <fu bar.com> wrote in message

 What you suggest sounds really promising Eric, and it would certainly


 tremendously with what I'm doing.

 So, what am I doing, specifically? Well, Mango has a clustering package,
 used for the caching, queuing, and execution of D classes across a LAN.
 Naturally, the classes passed around at runtime must be known at
 compile-time.

 Within a cluster, the server (storage) nodes get around this problem by
 maintaining such classes in serialized form only. That is, they


 avoid instantiating an instance (otherwise they'd need to be compiled


 every single possible class that might be stored).

 The cluster-clients, on the other hand, do need to know about each class


 since they will receive and operate upon concrete class instances. These
 classes must be known at compile time. For certain applications this is


 a restriction of any kind. In fact, it may actually be viewed as


 benefit.

 However, most software systems evolve rather dynamically, and rebooting


 entire operational network to get some new class-instances configured


 the cluster is just not practical.

 That's where DLL's (or shared libs) step in. In particular, the


 package would benefit greatly if the mobile classes involved were


 as discrete dll's. That way, it would be easy to ship them around the
 cluster too (as files), and they'd 'attach' to client nodes as


 This is very similar in approach to how servlets are loaded dynamically


 a running server (and reloaded when they are seen to change).

 The other factor involved in such an approach is this: these mobile


 often need to use resources outside of their own codebase (think Mango
 classes, or a database, or whatever). One does not want to bloat the


 dll's with such artifacts ~ they should be bound when said dll is loaded
 instead. That is, the Mango library itself should be a dll.

 Being able to do this cleanly, elegantly, efficiently, and robustly is
 important. I think something needs to be done to bring D up-to-date in


 respect.

 How about it?




 "pragma" <EricAnderton at yahoo dot compragma_member pathlink.com> wrote


 message news:cf80ak$m3v$1 digitaldaemon.com...
 In article <cf73n3$b1l$2 digitaldaemon.com>, Lars Ivar Igesund says...
antiAlias wrote:

 Currently, D libraries are predominantly linked in a static





 have
 a fairly substantial OO library that I'd really like to distribute





 dll/shared-lib, but there are apparently a number of issues that





 one
 doing so. I may have all of this completely wrong, and I'm really



 for guidance more that anything else:

 1) each DLL has its own GC. Crossing DLL boundaries is a problem





 memory
 allocations, especially for OO libraries (new doesn't work; some



 allocate within the DLL but the reference is held by the client



 etc).

 2) as I understand it, Exceptions do not cross DLL boundaries





 One of the goals of providing a library is "ease of use" for the





 user. I
 don't wish to make anyone jump through hoops just to use an OO





 from a
 DLL, yet the library really needs to be shareable (there's





 a
 very large number of small bound clients, so one would hope to





 static-binding where possible). Can someone point me in the right



 Or can we get some support from the compiler, if it's necessary?





 all,
 a new language is a tough sell without good, easy to use libraries





 right?

I have to say that I agree. DLL's are supposed to be the glorious way forward (at least it is what is preached outside the D world), but




rather difficult to use correctly and safely seems to keep most




from actually creating any.

At the very least, strategies for how to overcome the problems




above, should be collected (at the Wiki, I suppose). Maybe it's




to make tools that can create the factories, stubs, etc




but it sure would be nice to be able to use them the easy way.

I would like to come with suggestions for how to 'fix' the DLL's, but




don't think I really have the know-how to even suggest. I *do* know
though, that I would like to not have to use reference-counting.

Lars Ivar Igesund

Honestly, I've already surmounted a huge number of issues regarding D

 my time writing DSP.  I've had to devise some workarounds including,



 not
 limited to: object proxies, pointer lists and event messaging to



 dll
 unloads.  I like your suggestion that solutions should be up on the



 and I
 may publish my findings there. :)  Like everyone in this thread, I



 more
 from D with regard to how libraries are handled.

 Here's my $0.02:

 What is really missing is giving the DLL's a larger role in the eyes



 the
 garbage collector.  Having a separate GC on each library works well



 having
 D inter-operate with different languages, but within a 100% D project



 can
 become a hinderance.  Without close and careful management of where a

 object "lives", releasing a DLL mid-process can be disasterous.



 this
 isn't any different from what we've already come to know about C and



 its
 just something we would all rather live without (what with D already

 strides to overcome other problems in C++).

 Two years ago, I put down development of my own GC-based runtime



 for C++
   I came across this issue and devised some solutions for it, but was

 implement it as my GC engine had some impossible-to-debug quirks with



 For
 all that effort, I did learn some rather invaluable lessons about the

 collector has on a language.

 Hooking a GC into another dll isn't that hard to do, as long as one is

 to take on the notion of D-platform-dependent libraries.  Ultimately,



 realized
 that the problem regarding Dll's and GC engines is easy provided you



 answer
 one question:

 Does a given pointer represent a pointer to code on a given DLL, or to



 valid
 root in a given DLL?

 From this we can deduce the rest of the information we need to do

 else dynamically.  If a DLL has no vtables or delegates pointing to



 code,
 and no pointers elsewhere to any other roots within the DLL, then



 are no
 dependencies on that DLL and it may be dismissed.  This leads up to



 notion
 that DLL's themselves may be managed by utilizing the gc.

 A DLL can be treated as a collectable object, provided that its root

 and _entire code space_ are set as roots to be scanned by the hosting

 garbage collector.  Such A DLL can be unloaded from the process in a

 analagous to collection of a typical object (i.e. lazy destruction and

 of resources).

 The result is something that is almost totally transparent to the

 provided that phobos is given some additional support (outside of

 for DLLs.  Careful object management and prodding the GC should be



 to get
 a library to release/unload/close whenever needed.

 By constrast an explicit and immediate unload of a DLL requires far



 plumbing and participation on behalf of the library developer and



 user
 alike.  Collectable DLL's, IMO are the way forward for D.

 - Pragma




Aug 19 2004
parent reply pragma <EricAnderton at yahoo dot com> <pragma_member pathlink.com> writes:
FYI: this is a long post, please read.  Thank you. :)

In article <cg41tm$2u6a$1 digitaldaemon.com>, Matthew says...
"antiAlias" <fu bar.com> wrote in message
news:cg408a$2tge$1 digitaldaemon.com...
 I agree that #1 (the shared GC) is a primary issue. On the face of it, what
 Eric describes (below) sounds really attractive.

It sounds promising. I'd like to hear more fine details, though.

I'll work on a more detailed treatment as soon as time permits. I'll have to first go back through my old source/notes and make sure that there's nothing that I've managed to miss. One thing I will say though: No matter how many times I revisit the problem, the businss of explicitly unloading a library at runtime has ugly consequences regardless of how the GC is hooked. Also, I blame languages like Java and C# for raising our expectations of how this should be handled. I don't think the problem can be completely solved for in-memory objects, without resorting to proxies and/or notification lists.
I'd also like to hear if his ideas would require changes to std.loader (as I'm
itching for an excuse to rewrite that
stillborn obscenity).

I think my first reaction to reading that source was: "This compiled?" (j/k) I wouldn't anticipate need to change std.loader drastically. Outside of that, I'd love to see the thread-local storage bits broken out into another library or as an extension to std.thread. ;) One question though: is all the extra ref-counting code needed for linux libraries, or does it supply some extra value to both Win32 and Linux environments?
I'd also like to hear Walter's opinions on the matter. I think this issue is of
sufficient import to be a 1.0
prerequesite, don't you?

I couldn't agree more. I too, would like to hear what direction things will take with respect to dll's.
 Other than that, what about the exception-boundary issue?

Well, D's going to have an ABI, and since all exceptions are going to co-exist memorywise (when the GC's linearised/homogenised), what's the prob?

With respect to Kris' concern about handling exceptions, its really obnoxious how an uncaught exception within a library kills your app. Aside from making all of my libraries behave like class-factories, I've taken to using methods that do this:
 int someMethod(int foo){ /* impl */ }

..to be called and exported by a dll stub function:
 export(Windows) Exception someMethod(int foo,out _returnval){
   Exception _exception;
   try{ _returnval = someMethod(foo); }
   catch(Exception e){ _exception = e; }
   return(_exception);
 }

You can use a similar stub on the calling side that wraps the function pointer that you grab from the library. Meanwhile (on a slightly OT note), I'm still working on some of the more tricky aspects of dll's in D. In particular, I've tracked one really nasty bug down to (what looks like) the digitalmars-C backend:
 // deceptively simple example.
 import std.c.windows.windows;
 void main(){
   HMODULE mod = LoadLibrary("mydll.dll");
   printf("freeing...");
   FreeLibrary(mod);
   printf("You will never see this print.\n");
 }

(Matthew, Kris, have you had this problem on your Windows machines? I've done this on two separate boxes with the same result. If you two or anyone else can confirm this, I'll go ahead and post it to the bugs NG) Basically, stdout and stdin are "automagically" set to EOF (or some similar state) after the call to FreeLibrary(): nothing goes in and nothing comes out. Everything else runs fine, no exceptions are thrown, and GetLastError() faithfully returns 0. I've been able to recreate the above in DMC, with a 100% C-built Dll using the same .def file as the mydll sample. The results are also the same when calling that dll from a host program written in MSVC6, DMD and DMC. Unless I'm horribly mistaken on how to do compose dll's using Digitalmars' technology, this is what you get the instant you unload any DMC/DMD built dll. The problem seems to only manifest when a proper DllMain() method is exported from the library. If none is provided, or if the given implementation can be optimized away, the error does not ocurr. This caused me hours upon hours of anguish trying to figure out why in my DSP/Mango server kept quietly halting on me: it was waiting for console input to terminate, but Mango's Stdin throws on EOF. :( - Pragma
Aug 20 2004
next sibling parent reply "Matthew" <admin.hat stlsoft.dot.org> writes:
I've read it once, but want to take some time to think before I respond to some
of the points.

Let me pose my question in a more direct manner:

AFAICS, one of the biggest problems is the ability to be able to use DLLs with
D in *all* of the following guises:

1. D exe, C dll. Communication by plain C-API function calls. All resources
returned whence they came.
2. C exe, D dll. Communication via extern(C) calls and/or interfaces with
well-known vtable layout (e.g. COM). All
resources returned whence they came
3. D exe, D dll, Communication via extern(C) calls and/or interfaces with
well-known vtable layout (e.g. COM). All
resources returned whence they came
4. D exe, D dll, Communication via extern(C) calls and/or interfaces with
well-known vtable layout (e.g. COM). Memory
allocated hither and used safely thither
5. D exe, D dll, Communication via extern(C) calls and/or extern(D) calls
and/or interfaces with well-known vtable
layout (e.g. COM). Memory allocated hither and used safely thither
6. D exe, D dll, Communication via 5. + classes. (Not sure of these details.)

Note, for each of the above, you can permute by replacing exe with D client
code inside a D dll in any of cases 2-6!

Since D has, putatively at least, an ABI, all 6 (or 11) of these should, in
principle be realisable. Further,
commercially speaking, D *must* provide all of these, to not be abandoned by
developers more influenced by deadline and
pragmatism than idealism and performance - in other words, most of them.

To my mind, we have two choices. One option is that the GC and supporting
infrastructure is *always* in some DCore.dll -
i.e. there're no more statically linked programs - in the same vein as .NET.
The other option is that we come up with a
mechanism whereby each link-unit is able to detect whether the process in which
it is loaded already has a GC and, if
so, links to that, otherwise starting its own. The complication to this is that
if the first such link-unit is not the
process' exe, we have the issue whereby the GC might be prematurely unloaded
while other link-units are still depending
on it. This could, hopefully(!), be resolved be having dependent link-units
hold an independent dynamic-load reference
on the GC's owning DLL.

Thoughts?

Walter, I'd be very interested in your thoughts on this, both on my comments on
the need for this commercially, and also
on possible implementation mechanisms.




"pragma" <EricAnderton at yahoo dot compragma_member pathlink.com> wrote in
message
news:cg5184$c7u$1 digitaldaemon.com...
 FYI: this is a long post, please read.  Thank you. :)

 In article <cg41tm$2u6a$1 digitaldaemon.com>, Matthew says...
"antiAlias" <fu bar.com> wrote in message
news:cg408a$2tge$1 digitaldaemon.com...
 I agree that #1 (the shared GC) is a primary issue. On the face of it, what
 Eric describes (below) sounds really attractive.

It sounds promising. I'd like to hear more fine details, though.

I'll work on a more detailed treatment as soon as time permits. I'll have to first go back through my old source/notes and make sure that there's nothing that I've managed to miss. One thing I will say though: No matter how many times I revisit the problem, the businss of explicitly unloading a library at runtime has ugly consequences regardless of how the GC is hooked. Also, I blame languages like Java and C# for raising our expectations of how this should be handled. I don't think the problem can be completely solved for in-memory objects, without resorting to proxies and/or notification lists.
I'd also like to hear if his ideas would require changes to std.loader (as I'm
itching for an excuse to rewrite that
stillborn obscenity).

I think my first reaction to reading that source was: "This compiled?" (j/k) I wouldn't anticipate need to change std.loader drastically. Outside of that, I'd love to see the thread-local storage bits broken out into another library or as an extension to std.thread. ;) One question though: is all the extra ref-counting code needed for linux libraries, or does it supply some extra value to both Win32 and Linux environments?
I'd also like to hear Walter's opinions on the matter. I think this issue is of
sufficient import to be a 1.0
prerequesite, don't you?

I couldn't agree more. I too, would like to hear what direction things will take with respect to dll's.
 Other than that, what about the exception-boundary issue?

Well, D's going to have an ABI, and since all exceptions are going to co-exist memorywise (when the GC's linearised/homogenised), what's the prob?

With respect to Kris' concern about handling exceptions, its really obnoxious how an uncaught exception within a library kills your app. Aside from making all of my libraries behave like class-factories, I've taken to using methods that do this:
 int someMethod(int foo){ /* impl */ }

..to be called and exported by a dll stub function:
 export(Windows) Exception someMethod(int foo,out _returnval){
   Exception _exception;
   try{ _returnval = someMethod(foo); }
   catch(Exception e){ _exception = e; }
   return(_exception);
 }

You can use a similar stub on the calling side that wraps the function pointer that you grab from the library. Meanwhile (on a slightly OT note), I'm still working on some of the more tricky aspects of dll's in D. In particular, I've tracked one really nasty bug down to (what looks like) the digitalmars-C backend:
 // deceptively simple example.
 import std.c.windows.windows;
 void main(){
   HMODULE mod = LoadLibrary("mydll.dll");
   printf("freeing...");
   FreeLibrary(mod);
   printf("You will never see this print.\n");
 }

(Matthew, Kris, have you had this problem on your Windows machines? I've done this on two separate boxes with the same result. If you two or anyone else can confirm this, I'll go ahead and post it to the bugs NG) Basically, stdout and stdin are "automagically" set to EOF (or some similar state) after the call to FreeLibrary(): nothing goes in and nothing comes out. Everything else runs fine, no exceptions are thrown, and GetLastError() faithfully returns 0. I've been able to recreate the above in DMC, with a 100% C-built Dll using the same .def file as the mydll sample. The results are also the same when calling that dll from a host program written in MSVC6, DMD and DMC. Unless I'm horribly mistaken on how to do compose dll's using Digitalmars' technology, this is what you get the instant you unload any DMC/DMD built dll. The problem seems to only manifest when a proper DllMain() method is exported from the library. If none is provided, or if the given implementation can be optimized away, the error does not ocurr. This caused me hours upon hours of anguish trying to figure out why in my DSP/Mango server kept quietly halting on me: it was waiting for console input to terminate, but Mango's Stdin throws on EOF. :( - Pragma

Aug 21 2004
parent "antiAlias" <fu bar.com> writes:
Matthew;

As far as the GC is concerned, it would be wonderful to stuff that into a
DLL ... that would solve a major problem right off the bat. Putting Phobos
in a DLL would be a good idea also (no duplication of code across DLL
instances).

If subsequent DLL's were loaded as collectable entities (wrapped by a class;
or perhaps /as/ a class) then the GC could handle all the murky ref-counting
in its own inimitable fashion (invoking the destructor when the DLL is no
longer referenced). That would eliminate another sticky wicket; as Eric
pointed out.

Those two get my immediate support; they would help tremendously with both
Mango clustering and with the servlet-engine.

As to how one gains access to a class within the DLL ... I'd be happy with a
simple and convenient means of accessing a factory method from the DLL, and
going from there. Of course, what you are describing would be infinitely
superior; but I'd be happy to wait for it if the primary issues were taken
care of (shareable GC; DLLs as collectible entities).



"Matthew" <admin.hat stlsoft.dot.org> wrote in message
news:cg8kuk$2il8$1 digitaldaemon.com...
 I've read it once, but want to take some time to think before I respond to

 Let me pose my question in a more direct manner:

 AFAICS, one of the biggest problems is the ability to be able to use DLLs

 1. D exe, C dll. Communication by plain C-API function calls. All

 2. C exe, D dll. Communication via extern(C) calls and/or interfaces with

 resources returned whence they came
 3. D exe, D dll, Communication via extern(C) calls and/or interfaces with

 resources returned whence they came
 4. D exe, D dll, Communication via extern(C) calls and/or interfaces with

 allocated hither and used safely thither
 5. D exe, D dll, Communication via extern(C) calls and/or extern(D) calls

 layout (e.g. COM). Memory allocated hither and used safely thither
 6. D exe, D dll, Communication via 5. + classes. (Not sure of these

 Note, for each of the above, you can permute by replacing exe with D

 Since D has, putatively at least, an ABI, all 6 (or 11) of these should,

 commercially speaking, D *must* provide all of these, to not be abandoned

 pragmatism than idealism and performance - in other words, most of them.

 To my mind, we have two choices. One option is that the GC and supporting

 i.e. there're no more statically linked programs - in the same vein as

 mechanism whereby each link-unit is able to detect whether the process in

 so, links to that, otherwise starting its own. The complication to this is

 process' exe, we have the issue whereby the GC might be prematurely

 on it. This could, hopefully(!), be resolved be having dependent

 on the GC's owning DLL.

 Thoughts?

 Walter, I'd be very interested in your thoughts on this, both on my

 on possible implementation mechanisms.




 "pragma" <EricAnderton at yahoo dot compragma_member pathlink.com> wrote

 news:cg5184$c7u$1 digitaldaemon.com...
 FYI: this is a long post, please read.  Thank you. :)

 In article <cg41tm$2u6a$1 digitaldaemon.com>, Matthew says...
"antiAlias" <fu bar.com> wrote in message



 I agree that #1 (the shared GC) is a primary issue. On the face of




 Eric describes (below) sounds really attractive.

It sounds promising. I'd like to hear more fine details, though.

I'll work on a more detailed treatment as soon as time permits. I'll


 first go back through my old source/notes and make sure that there's


 that I've managed to miss.

 One thing I will say though: No matter how many times I revisit the


 businss of explicitly unloading a library at runtime has ugly


 regardless of how the GC is hooked.  Also, I blame languages like Java


 for raising our expectations of how this should be handled.  I don't


 problem can be completely solved for in-memory objects, without


 proxies and/or notification lists.

I'd also like to hear if his ideas would require changes to std.loader



stillborn obscenity).

I think my first reaction to reading that source was: "This compiled?"


 I wouldn't anticipate need to change std.loader drastically.  Outside of


 I'd love to see the thread-local storage bits broken out into another


 as an extension to std.thread. ;)

 One question though: is all the extra ref-counting code needed for linux
 libraries, or does it supply some extra value to both Win32 and Linux
 environments?

I'd also like to hear Walter's opinions on the matter. I think this



prerequesite, don't you?

I couldn't agree more. I too, would like to hear what direction things


 take with respect to dll's.
 Other than that, what about the exception-boundary issue?

Well, D's going to have an ABI, and since all exceptions are going to



linearised/homogenised), what's the prob?

With respect to Kris' concern about handling exceptions, its really


 how an uncaught exception within a library kills your app.  Aside from


 all of my libraries behave like class-factories, I've taken to using


 that do this:

 int someMethod(int foo){ /* impl */ }

..to be called and exported by a dll stub function:
 export(Windows) Exception someMethod(int foo,out _returnval){
   Exception _exception;
   try{ _returnval = someMethod(foo); }
   catch(Exception e){ _exception = e; }
   return(_exception);
 }

You can use a similar stub on the calling side that wraps the function


 that you grab from the library.

 Meanwhile (on a slightly OT note), I'm still working on some of the more


 aspects of dll's in D.  In particular, I've tracked one really nasty bug


 (what looks like) the digitalmars-C backend:

 // deceptively simple example.
 import std.c.windows.windows;
 void main(){
   HMODULE mod = LoadLibrary("mydll.dll");
   printf("freeing...");
   FreeLibrary(mod);
   printf("You will never see this print.\n");
 }

(Matthew, Kris, have you had this problem on your Windows machines?


 this on two separate boxes with the same result.  If you two or anyone


 confirm this, I'll go ahead and post it to the bugs NG)

 Basically, stdout and stdin are "automagically" set to EOF (or some


 state) after the call to FreeLibrary(): nothing goes in and nothing


 Everything else runs fine, no exceptions are thrown, and GetLastError()
 faithfully returns 0.

 I've been able to recreate the above in DMC, with a 100% C-built Dll


 same .def file as the mydll sample.  The results are also the same when


 that dll from a host program written in MSVC6, DMD and DMC.  Unless I'm


 mistaken on how to do compose dll's using Digitalmars' technology, this


 you get the instant you unload any DMC/DMD built dll.

 The problem seems to only manifest when a proper DllMain() method is


 from the library.  If none is provided, or if the given implementation


 optimized away, the error does not ocurr.

 This caused me hours upon hours of anguish trying to figure out why in


 DSP/Mango server kept quietly halting on me: it was waiting for console


 terminate, but Mango's Stdin throws on EOF.  :(

 - Pragma


Aug 21 2004
prev sibling next sibling parent reply "Matthew" <admin.hat stlsoft.dot.org> writes:
I've read it once, but want to take some time to think before I respond to some
of the points.

Let me pose my question in a more direct manner:

AFAICS, one of the biggest problems is the ability to be able to use DLLs with
D in *all* of the following guises:

1. D exe, C dll. Communication by plain C-API function calls. All resources
returned whence they came.
2. C exe, D dll. Communication via extern(C) calls and/or interfaces with
well-known vtable layout (e.g. COM). All
resources returned whence they came
3. D exe, D dll, Communication via extern(C) calls and/or interfaces with
well-known vtable layout (e.g. COM). All
resources returned whence they came
4. D exe, D dll, Communication via extern(C) calls and/or interfaces with
well-known vtable layout (e.g. COM). Memory
allocated hither and used safely thither
5. D exe, D dll, Communication via extern(C) calls and/or extern(D) calls
and/or interfaces with well-known vtable
layout (e.g. COM). Memory allocated hither and used safely thither
6. D exe, D dll, Communication via 5. + classes. (Not sure of these details.)

Note, for each of the above, you can permute by replacing exe with D client
code inside a D dll in any of cases 2-6!

Since D has, putatively at least, an ABI, all 6 (or 11) of these should, in
principle be realisable. Further,
commercially speaking, D *must* provide all of these, to not be abandoned by
developers more influenced by deadline and
pragmatism than idealism and performance - in other words, most of them.

To my mind, we have two choices. One option is that the GC and supporting
infrastructure is *always* in some DCore.dll -
i.e. there're no more statically linked programs - in the same vein as .NET.
The other option is that we come up with a
mechanism whereby each link-unit is able to detect whether the process in which
it is loaded already has a GC and, if
so, links to that, otherwise starting its own. The complication to this is that
if the first such link-unit is not the
process' exe, we have the issue whereby the GC might be prematurely unloaded
while other link-units are still depending
on it. This could, hopefully(!), be resolved be having dependent link-units
hold an independent dynamic-load reference
on the GC's owning DLL.

Thoughts?

Walter, I'd be very interested in your thoughts on this, both on my comments on
the need for this commercially, and also
on possible implementation mechanisms.




"pragma" <EricAnderton at yahoo dot compragma_member pathlink.com> wrote in
message
news:cg5184$c7u$1 digitaldaemon.com...
 FYI: this is a long post, please read.  Thank you. :)

 In article <cg41tm$2u6a$1 digitaldaemon.com>, Matthew says...
"antiAlias" <fu bar.com> wrote in message
news:cg408a$2tge$1 digitaldaemon.com...
 I agree that #1 (the shared GC) is a primary issue. On the face of it, what
 Eric describes (below) sounds really attractive.

It sounds promising. I'd like to hear more fine details, though.

I'll work on a more detailed treatment as soon as time permits. I'll have to first go back through my old source/notes and make sure that there's nothing that I've managed to miss. One thing I will say though: No matter how many times I revisit the problem, the businss of explicitly unloading a library at runtime has ugly consequences regardless of how the GC is hooked. Also, I blame languages like Java and C# for raising our expectations of how this should be handled. I don't think the problem can be completely solved for in-memory objects, without resorting to proxies and/or notification lists.
I'd also like to hear if his ideas would require changes to std.loader (as I'm
itching for an excuse to rewrite that
stillborn obscenity).

I think my first reaction to reading that source was: "This compiled?" (j/k) I wouldn't anticipate need to change std.loader drastically. Outside of that, I'd love to see the thread-local storage bits broken out into another library or as an extension to std.thread. ;) One question though: is all the extra ref-counting code needed for linux libraries, or does it supply some extra value to both Win32 and Linux environments?
I'd also like to hear Walter's opinions on the matter. I think this issue is of
sufficient import to be a 1.0
prerequesite, don't you?

I couldn't agree more. I too, would like to hear what direction things will take with respect to dll's.
 Other than that, what about the exception-boundary issue?

Well, D's going to have an ABI, and since all exceptions are going to co-exist memorywise (when the GC's linearised/homogenised), what's the prob?

With respect to Kris' concern about handling exceptions, its really obnoxious how an uncaught exception within a library kills your app. Aside from making all of my libraries behave like class-factories, I've taken to using methods that do this:
 int someMethod(int foo){ /* impl */ }

..to be called and exported by a dll stub function:
 export(Windows) Exception someMethod(int foo,out _returnval){
   Exception _exception;
   try{ _returnval = someMethod(foo); }
   catch(Exception e){ _exception = e; }
   return(_exception);
 }

You can use a similar stub on the calling side that wraps the function pointer that you grab from the library. Meanwhile (on a slightly OT note), I'm still working on some of the more tricky aspects of dll's in D. In particular, I've tracked one really nasty bug down to (what looks like) the digitalmars-C backend:
 // deceptively simple example.
 import std.c.windows.windows;
 void main(){
   HMODULE mod = LoadLibrary("mydll.dll");
   printf("freeing...");
   FreeLibrary(mod);
   printf("You will never see this print.\n");
 }

(Matthew, Kris, have you had this problem on your Windows machines? I've done this on two separate boxes with the same result. If you two or anyone else can confirm this, I'll go ahead and post it to the bugs NG) Basically, stdout and stdin are "automagically" set to EOF (or some similar state) after the call to FreeLibrary(): nothing goes in and nothing comes out. Everything else runs fine, no exceptions are thrown, and GetLastError() faithfully returns 0. I've been able to recreate the above in DMC, with a 100% C-built Dll using the same .def file as the mydll sample. The results are also the same when calling that dll from a host program written in MSVC6, DMD and DMC. Unless I'm horribly mistaken on how to do compose dll's using Digitalmars' technology, this is what you get the instant you unload any DMC/DMD built dll. The problem seems to only manifest when a proper DllMain() method is exported from the library. If none is provided, or if the given implementation can be optimized away, the error does not ocurr. This caused me hours upon hours of anguish trying to figure out why in my DSP/Mango server kept quietly halting on me: it was waiting for console input to terminate, but Mango's Stdin throws on EOF. :( - Pragma

Aug 21 2004
parent pragma <EricAnderton at yahoo dot com> <pragma_member pathlink.com> writes:
In article <cg8kut$2ilc$1 digitaldaemon.com>, Matthew says...
To my mind, we have two choices. One option is that the GC and supporting
infrastructure is *always* in some DCore.dll -
i.e. there're no more statically linked programs - in the same vein as .NET.
The other option is that we come up with a
mechanism whereby each link-unit is able to detect whether the process in which
it is loaded already has a GC and, if
so, links to that, otherwise starting its own. The complication to this is that
if the first such link-unit is not the
process' exe, we have the issue whereby the GC might be prematurely unloaded
while other link-units are still depending
on it. This could, hopefully(!), be resolved be having dependent link-units
hold an independent dynamic-load reference
on the GC's owning DLL.

Thoughts?

I like the idea, but it represents quite a paradigm shift for D. Also, any time you introduce a platform library, you have the messy consequences of library versioning and which library instance (if multiple are present) is used on the search path. - Pragma
Aug 21 2004
prev sibling parent reply "Matthew" <admin.hat stlsoft.dot.org> writes:
"pragma" <EricAnderton at yahoo dot compragma_member pathlink.com> wrote in
message
news:cg5184$c7u$1 digitaldaemon.com...
 FYI: this is a long post, please read.  Thank you. :)

 In article <cg41tm$2u6a$1 digitaldaemon.com>, Matthew says...
"antiAlias" <fu bar.com> wrote in message
news:cg408a$2tge$1 digitaldaemon.com...
 I agree that #1 (the shared GC) is a primary issue. On the face of it, what
 Eric describes (below) sounds really attractive.

It sounds promising. I'd like to hear more fine details, though.

I'll work on a more detailed treatment as soon as time permits. I'll have to first go back through my old source/notes and make sure that there's nothing that I've managed to miss.

Ok. This is an issue that will run and run, I think. At least for a month or two, or until it's sorted, at least.
 One thing I will say though: No matter how many times I revisit the problem,
the
 businss of explicitly unloading a library at runtime has ugly consequences
 regardless of how the GC is hooked.

Can you give some more detailed examples. I'm an example kinda guy. :)
  Also, I blame languages like Java and C#
 for raising our expectations of how this should be handled.  I don't think the
 problem can be completely solved for in-memory objects, without resorting to
 proxies and/or notification lists.

I'd also like to hear if his ideas would require changes to std.loader (as I'm
itching for an excuse to rewrite that
stillborn obscenity).

I think my first reaction to reading that source was: "This compiled?" (j/k)

Can you be specific? I'm troubled by its implementations for certain reasons, but I'd like to hear your unalloyed criticisms.
 I wouldn't anticipate need to change std.loader drastically.  Outside of that,
 I'd love to see the thread-local storage bits broken out into another library
or
 as an extension to std.thread. ;)

Do you think we'll need to provide any additional mechanisms that will need to be standardised via std.loader? For example, GC-using D dlls might be required to export a specific entry point to facilitate GC-hooking, which would be built into std.loader.
 One question though: is all the extra ref-counting code needed for linux
 libraries, or does it supply some extra value to both Win32 and Linux
 environments?

Probably not for Linux, but I'm very cautious/cynical on this issue, as I've previously been bitten on some UNIXen that did not do internal ref-counting on dynamic libs. Hence, I think it's safest to do it ourselves.
I'd also like to hear Walter's opinions on the matter. I think this issue is of
sufficient import to be a 1.0
prerequesite, don't you?

I couldn't agree more. I too, would like to hear what direction things will take with respect to dll's.

I've posted another, more detailed, response on this in this thread. I'd be keen to hear your ideas on that.
 Other than that, what about the exception-boundary issue?

Well, D's going to have an ABI, and since all exceptions are going to co-exist memorywise (when the GC's linearised/homogenised), what's the prob?

With respect to Kris' concern about handling exceptions, its really obnoxious how an uncaught exception within a library kills your app. Aside from making all of my libraries behave like class-factories, I've taken to using methods that do this:

Yes, exceptions also need sorting from a multiple library point of view. As I say in the other post, I'm beginning to think that D link-units need to search each other out at runtime, and coordinate their activities somehow. We've just got to hope that it turns out to be less messy than COM or, heaven forefend, .NET!
 int someMethod(int foo){ /* impl */ }

..to be called and exported by a dll stub function:
 export(Windows) Exception someMethod(int foo,out _returnval){
   Exception _exception;
   try{ _returnval = someMethod(foo); }
   catch(Exception e){ _exception = e; }
   return(_exception);
 }

You can use a similar stub on the calling side that wraps the function pointer that you grab from the library. Meanwhile (on a slightly OT note), I'm still working on some of the more tricky aspects of dll's in D. In particular, I've tracked one really nasty bug down to (what looks like) the digitalmars-C backend:
 // deceptively simple example.
 import std.c.windows.windows;
 void main(){
   HMODULE mod = LoadLibrary("mydll.dll");
   printf("freeing...");
   FreeLibrary(mod);
   printf("You will never see this print.\n");
 }

(Matthew, Kris, have you had this problem on your Windows machines? I've done this on two separate boxes with the same result. If you two or anyone else can confirm this, I'll go ahead and post it to the bugs NG)

I confess I've done ~0 dynamic libs with D. :-)
 Basically, stdout and stdin are "automagically" set to EOF (or some similar
 state) after the call to FreeLibrary(): nothing goes in and nothing comes out.
 Everything else runs fine, no exceptions are thrown, and GetLastError()
 faithfully returns 0.

 I've been able to recreate the above in DMC, with a 100% C-built Dll using the
 same .def file as the mydll sample.  The results are also the same when calling
 that dll from a host program written in MSVC6, DMD and DMC.  Unless I'm
horribly
 mistaken on how to do compose dll's using Digitalmars' technology, this is what
 you get the instant you unload any DMC/DMD built dll.

 The problem seems to only manifest when a proper DllMain() method is exported
 from the library.  If none is provided, or if the given implementation can be
 optimized away, the error does not ocurr.

 This caused me hours upon hours of anguish trying to figure out why in my
 DSP/Mango server kept quietly halting on me: it was waiting for console input
to
 terminate, but Mango's Stdin throws on EOF.  :(

 - Pragma

Aug 21 2004
parent pragma <EricAnderton at yahoo dot com> <pragma_member pathlink.com> writes:
In article <cg8png$2ltl$1 digitaldaemon.com>, Matthew says...
"pragma" <EricAnderton at yahoo dot compragma_member pathlink.com> wrote in 
 One thing I will say though: No matter how many times I revisit the problem,
the
 businss of explicitly unloading a library at runtime has ugly consequences
 regardless of how the GC is hooked.

Can you give some more detailed examples. I'm an example kinda guy. :)

I'll take an oversimplified example from my D-Servlet Pages project. void foo(Request req,Response res){ // ServletLibrary proxies all the exports from the dll // and exposes some extra housekeeping functions ServletLibrary library = getServletLibrary("mylib.dll"); // library is queried for a servlet. The servlet is created inside the dll DSPServlet servlet = library.getServlet(); // Do some work (generate HTML, and so forth) servlet.service(req,res); // This frees the library. It is now no longer in memory library.unload(); // "servlet" is now invalid (see below) } No matter which side has the responsibility for performing GC operations and memory allocations, the V-table for any object always lives where it was created. This application in particular rebuilds dlls on demand, so references to servlets can be invalidated at a drop of a hat, across multiple threads.
 I think my first reaction to reading that source was: "This compiled?" (j/k)

Can you be specific?

Honestly, it comes down to a matter of coding style: I'm just not used to reading your code. :) You say poh-tay-toh I say po-tot-oh... But I understand why its organized the way it is, and I feel its a very solid lib. The only thing I'd have done differently would be to roll HXModule into a non-auto class that handles all the refcounting, while wrapping the linux functions with Win32-like functions (or the other way around), so there's less code in there.
I'm troubled by its implementations for certain reasons, but I'd like to hear
your unalloyed criticisms.

 I wouldn't anticipate need to change std.loader drastically.  Outside of that,
 I'd love to see the thread-local storage bits broken out into another library
or
 as an extension to std.thread. ;)

Do you think we'll need to provide any additional mechanisms that will need to be standardised via std.loader? For example, GC-using D dlls might be required to export a specific entry point to facilitate GC-hooking, which would be built into std.loader.

If we're going to go with hooking rather than a GCCore.dll-type solution (from your other post, I like that idea), then yea, that would be best served internally by loader. A non-auto class (DllModule maybe?) would be a nice touch. Also an 'event' (I guess a delegate[] in D is close enough) that is called when a dll is finally unloaded (refcount goes to zero), would be a *very* nice addition.
Yes, exceptions also need sorting from a multiple library point of view. As I
say in the other post, I'm beginning to
think that D link-units need to search each other out at runtime, and
coordinate their activities somehow. We've just
got to hope that it turns out to be less messy than COM or, heaven forefend,
.NET!

I confess I've done ~0 dynamic libs with D. :-)

Hehe.. we'll fix that. ;) Walter has made it easy as sin to create .dll's in D. What's missing is a D-standard stub that is /implicitly/ added to a library along with classinfo, exception piping, GC hooking, etc etc... one becomes painfully aware of all this only *after* you start working with dll's heavily. Its even worse coming from using Java's classloader or .NET assemblies; D has a very long way to go in this department. - Pragma
Aug 21 2004