16

Suppose I have two projects that I would like to link together:

  • A C++ library compiled with Visual C++ to a DLL file.
  • A C++ executable compiled with C++ Builder that uses the classes in the library.

I realize that there is no standard C++ ABI and that any attempts to directly link these two C++ projects together will fail. What is a good, automated way of creating a compatibility layer that allows me to accomplish this?

For example, conceivably the C++ library could expose itself via a C interface. Then the executable would have some C++ classes that wrap the C interface exposed by the C++ library. Since there is a standard ABI for C, it would work.

The only question is how to automatically create the C interface and C++ wrapper classes - manually maintaining this would not be an option. The SWIG project looks promising, but unfortunately, C++ is not one of the exits of SWIG listed on their web site. Is there a way to do what I want with SWIG? Or is there another project other than SWIG that would help me with this task?

Or am I going about this the wrong way?

Edit: The core C++ library is intended to be cross-platform. The executable, obviously, is Windows-specific. I don't want to pollute the core library to the extent that it becomes impossible to compile it on other platforms.

James Johnston
  • 9,264
  • 9
  • 48
  • 76
  • 1
    +1 for striving to keep you core business logic cross-platform. – emsr Aug 20 '12 at 15:32
  • How many classes/methods are we talking about. C shims that that take an opaque pointer to a C++ class and call the C++ method are not difficult although I admit it can get tedious. – emsr Aug 20 '12 at 15:35
  • For the initial project - not many classes. Think of this as practice for a much larger project, however. That project would ultimately involve a significant number of back-end classes being moved into the core C++ library. I think we would require automated code generation at that point. I agree that writing the C shims is easy. It's just that there will ultimately be too many of them to manually maintain. – James Johnston Aug 20 '12 at 15:58
  • Cross-platform and cross-compiler are different things. Be specific in your question. I could be "cross-platform" and if I use the same compiler for all the libs/executables on a given platform, then your question is moot. – Josh Petitt Aug 20 '12 at 16:41
  • @Josh Petitt: core logic should ultimately run on any operating system, any C++11 compiler. User interface code might be more flexible - for now, C++ and the VCL. It may be specific to one compiler/operating system, or perhaps be more general. Later on, it needs to have flexibility to target user interfaces like Qt, .NET WPF (SWIG can help with that I would think), other native widget toolkits - who knows what the next popular widget toolkit will be in 5 years? We want to be ready. – James Johnston Aug 20 '12 at 16:58

5 Answers5

5

If it only has to run on Windows, I would expose the classes as COM objects. They'll still be in a DLL and they can be used by any language which understands COM.

Ferruccio
  • 98,941
  • 38
  • 226
  • 299
  • Great - now can you suggest an automated tool for doing that which avoids polluting the original C++ library source code with COM garbage? The library is intended to be cross-platform, so directly using things like ATL on the "pristine" classes in the library just isn't going to fly. (Not to mention DLL hell that COM brings). – James Johnston Aug 20 '12 at 15:25
  • 5
    COM doesn't "bring dll hell", if you have a problem with something, at least just say you dislike it rather than make up nonsense excuses. As it is, you'd be advised to make them WinRT objects today (which are kind of COM objects) as you won't be able to get away from them soon. For an automated tool that will generate stubs for your methods - midl, or the DCE-RPC idl generator (that is cross-platform) will do this - you'll get in-process RPC calls which are almost as efficient as normal function calls. – gbjbaanb Aug 20 '12 at 16:01
4

The "standard" way of doing this, in Windows, is to use COM objects. So, that is certainly a good option to look at. In Linux systems, the module interaction model (e.g., executable-DLL interaction) is very different, and ABIs exist for C++.

If you would want to do this manually (create your own COM-like library), it can be a lot of work with many little tricky issues to take seriously. You'll need a cross-module RTTI system, you'll need an interface query/definition protocol, some mechanism to manage memory across modules, etc. Beyond that, to "automate" it, you will probably need a combination of MACROs and template meta-functions.

One cross-platform option that I would highly recommend that you consider or at least look at is using Boost.Python and the Python language as the "glue" between your modules. The Boost.Python library basically does the whole "automated exporting / importing of classes", but it exports your C++ classes and functions as Python classes and functions. And, it is completely non-intrusive and cross-platform, so this is really an ideal example of automated exporting. So, you might consider using Python to write your high-level glue-code, or using Python as an intermediate between the C++ modules, or even reworking the Boost.Python library to use only the "automated exporting" mechanisms to export to whatever interface system you design or use.

I'm sure there a plenty other similar libraries out there. But the number one question is, of course, do you really need this? You might be using a bazooka to kill a fly.

Mikael Persson
  • 18,174
  • 6
  • 36
  • 52
  • I'll have to look into that more. We have existing "legacy" user interface code that we want to interface with the proposed more modern C++ back-end. Since Boost.Python says it can be used to either call into Python or export classes out to Python, it seems like it could be made to work. But involving another language like Python in the mix sounds awfully kludgy. – James Johnston Aug 20 '12 at 16:02
0

Why not just compile the library with C++ builder as well?

Andreas Brinck
  • 51,293
  • 14
  • 84
  • 114
  • If we want to write a modern C++ back-end, we're looking for things like (1) lambda functions, (2) compatibility with libraries like TBB and OpenCV, (3) a good optimizing compiler for performance (Intel's compiler and Visual C++ both run circles around C++ Builder). These are things that C++ Builder doesn't support and honestly I don't think they will ever catch up with the competition in these regards. Holding back the quality of our new back-end code just to retain compatibility with this compiler seems like it would be a poor choice. – James Johnston Aug 20 '12 at 15:53
  • 1
    @JamesJohnston It sounds like your "problem" is your front end, not your back end. Is the complexity required to wrap up and make an interface to your spiffy back-end more effort that the work just to put a shiny new GUI on top of it? (Then you could use your favorite tool chain from front to back). – Josh Petitt Aug 20 '12 at 16:46
  • 1
    Yes, the front-end is the problem and that project has too much core logic mixed in with the user interface. What I would like to see is code slowly moved into a new back-end library DLL and the user interface modified to call into the DLL. Eventually the user interface can be rewritten at a later time and the same tool chain could be used everywhere. Ideally, everything could be rewritten at once but that's probably not realistic due to time/resource constraints - I don't think it would get traction. Ultimately the design would also enable targeting other operating systems besides Windows – James Johnston Aug 20 '12 at 16:55
0

Looking around at swig (I knew swig should be able to wrap C++ in C): SWIG and C++

emsr
  • 15,539
  • 6
  • 49
  • 62
0

If core library is cross-platform why not also write the UI as a cross-platform Qt application and build everything in Visual C++ on Windows.

Brian Ensink
  • 11,092
  • 3
  • 50
  • 63
  • Ultimately yes, that would be the idea. For now though, it's going to have to be a more gradual transition before we look at rewriting the UI, too. – James Johnston Aug 20 '12 at 16:07