Click here to Skip to main content
12,448,720 members (53,508 online)
Click here to Skip to main content
Add your own
alternative version

Stats

24K views
1.8K downloads
38 bookmarked
Posted

Designing the Interface of DLLs in C/C++ Projects

, 19 Feb 2016 CPOL
Rate this:
Please Sign up or sign in to vote.
An advice to make your DLL interface more attractive and easier-to-maintain even in cross-platform projects

Introduction

This tip assumes that you are familiar with DLL usage and related terms like static/dynamic linking. If you have no idea how to use DLLs, then read this tip after learning the DLL related basics here (cross-platform wikipedia page), here (windows) or here (unix: linux, bsd, osx, etc.).

My advice is to never use DLLs in your project if you don't have to because they are trouble. If you still have to fall back on putting some C/C++ code to DLLs (or you have to create a plug-in interface) and it's up to you to design the DLL interface (that is used only by your C/C++ code), then read along. There is a minimalistic zipped project file attached with a Visual C++ 2010 solution and a unix build script to demonstrate plugin (DLL / shared library) loading on Windows and unix (linux/bsd/osx) platforms.

How Should a DLL Interface Look Like In My Opinion

First, declare an interface (a class that has only pure virtual methods) in the public header file of your DLL. It's quite important to use only pure virtual methods! After this, put the only exported function to your DLL that returns a pointer to this interface. After this, in the private source files of your DLL, you can derive a class from this interface and implement its methods. Now the users of the DLL just call the interface getter method of the DLL and then continue using it in a nice C++ish way by calling the methods of the retrieved interface pointer.

Don't forget to read the attached example source code. It is very simple and short.

Why Is This Good?

  • It simply looks nicer.
  • As a result of the thin linking interface between your DLL and the module that uses it - just one exported DLL function - it's very easy to make this cross-platform because the ugly ifdefs and platform dependent code is minimal. The thin interface makes it easy to implement platform independent delay loading.
  • It's very easy to merge this DLL code into your application later as part of a refactorization if you decide to do so - it's a breeze.
  • Let's say you are writing a plug-in interface for your program - it's very easy to put internal plug-ins to your executable by implementing the DLL interface inside your program. It becomes very easy to switch between an built in functionality and one that is implemented in a DLL, for your executable both kinds are visible just as a simple interface pointer.

Versioning Plug-in DLLs (My Style)

There are a lot of ways to detect the version of plug-ins. For example, by coding the version into the versioninfo resource of the DLL, coding the version to the filename, getting the version by calling a version getter exported function of the DLL... I use a totally different approach that has several advantages over the previously listed methods.

Let's say I have a media player program and a codec plug-in for it with a specific interface. After some time, I release a new version of the media player that has a modified interface but I decide to release the plug-in for older versions of the media player as well. I do this by writing a single DLL that supports both the old and the new version of the plugin interface. The public interface header of my plug-in DLL will contain the declaration of both the old and the new version of the interface and it contains two exported functions: one of them returns the old, and the other returns the new interface pointer. The exported methods have different names of course: GetMediaPlayerInterface() and GetMediaPlayerInterface2(). The DLL implements both interfaces and inside it can use a lot of shared code between the two implementations and I have to maintain only one project for that.

I have a piece of code that can detect if a DLL exports some functions without actually loading the DLL. This piece of code is useful for many reasons: If you have to load a DLL to find out whether it is your plugin or not, then during your LoadLibrary() call the DllMain() of the library may be executed inside your process even if it is not your plugin. Another advantage is faster execution that may count a lot if your app has lots of plugins. Here is another tip that contains the code that detects whether a DLL exports your desired function(s) without loading it with LoadLibrary(): Checking for exported symbols/functions in a DLL without loading it.

Advices to Design the Interface of DLLs Written in C

I myself never use C in user applications and I'm generally against the use of C when development isn't very low/system-level and a reasonably good C++ compiler is available on the specified platform. If you have the sources of a DLL that is written in C, then you can do the following:

  1. If you want to keep the C interface, then do the following:
    • Declare a struct in the public header of your DLL. The members of this struct will be function pointers. This struct will be the equivalent of the C++ interface class.
    • Somewhere in your DLL, define a (static) instance of this struct and fill it with pointers to your function implementations.
    • Export a single function from the DLL that returns a const pointer to the previously defined (static) struct instance.
  2. Alternatively you can create a C++ "wrapper" interface from which you call the original C functions.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

pasztorpisti
Software Developer (Senior)
United Kingdom United Kingdom
No Biography provided

You may also be interested in...

Pro
Pro

Comments and Discussions

 
SuggestionMemory management Pin
imagiro21-Feb-16 20:24
memberimagiro21-Feb-16 20:24 
GeneralRe: Memory management Pin
pasztorpisti22-Feb-16 2:23
professionalpasztorpisti22-Feb-16 2:23 
QuestionNice tip - some clarifications about the projects' names Pin
StavrosApostolou18-Feb-16 2:56
memberStavrosApostolou18-Feb-16 2:56 
AnswerRe: Nice tip - some clarifications about the projects' names Pin
pasztorpisti18-Feb-16 9:48
professionalpasztorpisti18-Feb-16 9:48 
GeneralRe: Nice tip - some clarifications about the projects' names Pin
StavrosApostolou21-Feb-16 22:36
memberStavrosApostolou21-Feb-16 22:36 
AnswerRe: Nice tip - some clarifications about the projects' names Pin
pasztorpisti19-Feb-16 16:13
professionalpasztorpisti19-Feb-16 16:13 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.160811.3 | Last Updated 20 Feb 2016
Article Copyright 2012 by pasztorpisti
Everything else Copyright © CodeProject, 1999-2016
Layout: fixed | fluid