Boost logo

Boost :

From: Carl Daniel (cpdaniel_at_[hidden])
Date: 2002-03-26 10:13:19


From: "Stewart, Robert" <stewart_at_[hidden]>
> From: E. Gladyshev [mailto:egladysh_at_[hidden]]
> >
> > I don't think that it is pretty rare. If you worked
> > on huge and multi-team projects, then I am sure
> > you know that inter-module API's are specified
> > in C much more often than in C++. It is especially
>
> Not at all. Perhaps in your environment, that is the case, but there are
> many projects that are strictly C++.
>
> > important if the project has many DLL's or some of
> > the client code has to be C.
> > It is never a wise solution to export C++
> > classes from DLL's (remember name mangling...etc.)
>
> Since when? I used to do it frequently and I know the developers here that
> do NT work do it.

The problem, IMO, is that most projects mis-use DLLs (or shared libraries in general). If you're happy using the DLL as
a way to reduce link time on your project, then express your module interfaces as C++. If, on the other hand, you
expect to use DLLs as a way to modularize the deployment of a configurable product, or to reuse code in several
products, then a C++ interface is likely to be a liability.

Problems with C++ interfaces between Modules:
1. Naming compatbility
2. Binary layout compatibility
3. Exception propagation
4. Memory allocation and de-allocation (modules frequently have independent heaps).

Imagine the (not uncommon) case of "DLL as plug-in". By exposing a C++ api, you're requiring that every plug-in, even
those built by thrid parties, be built using the same toolchain as the base program. If building with GCC, it's
frequently necessary that they use the exact same compiler version and library version to be compatible. (VC has a
slightly better record in this regard, but in principal it's the same situation).

A C API, while still not guaranteed to be compatible (by any standard), is in practice almost always portable across
different compilers, versions, libraries, etc. This comes as a direct consequence of the fact that all modern OS's
express the system interface in C, thus requiring that all language tools for that platform be able to call C functions.

As an example, one of the products I work on has a plug-in architecture. Since the interface is expressed as C, I can
have one plug-in built with BCC, another with VC6, and another with VC7, all happily co-existing. In this case, I could
easily implement another plug-in in Delphi, and probably even in Fortran, and they'd all co-exist just fine.

> > Unfortunately our experience has nothing
> > to do with the real life requirements.
> > In most cases we don't have the total control
> > over how the project interfaces are defined.
> > I am sure you are well aware of that.
>
> It seems that each time someone tells you that there is no way to portably
> determine whether memory was allocated using ::new, malloc, some user- or
> system-defined heap, or the stack, so there's no way for shared_ptr to know
> how to release memory, and they suggest alternatives, you simply throw out
> additional requirements which disallow the suggestion.

Of course, there is NO way to determine how memory was allocated. IMO, a properly designed module interface will NEVER
delegate resource management responsibility to it's clients. If a DLL function allocates memory (or any other resource)
, the DLL must also expose a function to reclaim that memory (or resource) - any other combination is simply a time-bomb
waiting to go off. If you must use a library which exposes an interface which does delegate responsibility to you, it's
best to wrap that library in a new C++ class which completely encapsulates it's functionality and exposes a properly
designed interface to the rest of your application.

-cd


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk