Question

I was having a discussion with a colleague today. He claimed that writing a DLL in C would allow for any other application, written in whatever language, to use that DLL. BUT, if that DLL is written in C++, the number of applications that could use that DLL is limited (maybe because of language constraints).

  1. Is he correct in saying that?
  2. If you were to write a DLL that should be used by all sorts of applications written in all sorts of languages (but on the same platform; let's forget portability for a bit), would you write it in C/C++ and why?

I hope this question isn't a Gorilla vs. Shark kinda question. If it is, please close it.

Was it helpful?

Solution

Most languages provide an (easy) way to call C function from a DLL. It is not the case with C++, since C++ ABI (the binary interface of C++ function) is vendor-specific.

Added to that, it will be nearly impossible to interface with C++ DLL that use advanced C++ constructs like templating or the STL.

However, the contents of your DLL can be written in C++, you only need to make sure that your interface is C-compliant. To do that, do not use C++ constructs in you interface and surround your declarations with :

#ifdef __cpluscplus
extern "C" {
#endif

/* You declarations here */

#ifdef __cpluscplus
}
#endif

... this way, you wrap your C++ library with a C interface.

EDIT : As Mats Petersson wrote, do not forget to ensure that you handle every possible C++ exception in your wrapper.

OTHER TIPS

1) If the INTERFACE provided by the DLL is indeed a C++ interface, then yes, it makes it hard (if not impossible) for other languages to interface with the DLL.

C++ is more complex to interface with than C, because of the more complex structure of classes (this pointer being passed along, virtual function pointers/VTABLE layout) and exception handling (where the called code has to handle the fact that the exception happened in some way, and to do that, the code needs to be able to "unwind" the call-stack of the code that threw the exception and destroy any objects created on the way until it finds a catch - if that's not present in the call-stack within the DLL you'll get problems - this unwinding is not part of the C++ standard, because the standard does not wish to restrict which architectures and what features a processor needs/should have to implement C++ more than necessary). Catching exceptions within the DLL will solve issues here.

In other words, if the language is not C++ [and possibly from the same vendor] that is calling the code, there is a need for some handling of the C++ to whatever language is calling it. This can get pretty complicated.

Any C++ object need to be translated from/to the relevant language in the calling code. For basic types in common with C, this is generally not a problem, but classes, structs, etc, will have to be matched up against something compatible in the local language.

On the other hand: A C function is very easy to interface with: put the arguments on the stack, call the function, and clean up the arguments on return. Nothing strange happens, no hidden function parameters, no need to unwind stacks. The only slight complication is functions returning a struct (that is bigger than a certain size) - but that's a pretty special case in C. C's "objets" are much simpler, and most languages have types that correspond well to the basic C language types (but C style struct can still cause some interesting problems, and union can be a real challeng if it's used "cleverly").

2) Choosing languages is a complex business, and it largely depends on how the DLL is supposed to be used or what sort of interface it is supposed to provide, and what interfaces it itself should connect to - if your DLL is interfacing to another C++ DLL (or some other C++ code), then you probably want to use C++. But there are ways to produce a C++ DLL that has a C interface, by using extern "C" for the interface functions (and ensuring that nothing throws over the wall to "C", because that will definitely cause problems).

Conclusion: Obviously, by limiting the interface to "only use C++", then there is a further complication in that anyone using the library from, say, C, Python or Lisp [all of which can probably call C functions fairly easily], that user will have to wrap the C++ code in a C language wrapper. And yes, this can be done, and is used quite regularly when some really good library is available in C++, that someone wants to connect to a language that has a C style interface available. It's pretty much the same solution as the "provide a C to C++ interface within the DLL", except it's not provided by the producer of the DLL.

Each language has it's own characeristics like calling convention, stack setup and other stuff. Whenever you try to deal with function calls crossing language boundaries, you have to deal with this. Compilers support usually a variatey of calling conventions, so you have to make sure that the definitions and compilation is correct and then you can use any language to communicate with modules from others. The statement as such, that it is easier or harder to do, from one language or another as such, is not true, because you always have to deal with this at some point.

I select the language that suits me best for my task, not the other way around. When I write GUI apps I usually use Java, because it lets me concentrate on the solution instead of tracking memory. :) When I want performance I use C or C++ or even assembler, so the choice of language depends on what I intend to do with it or how my environment looks.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top