[Okta Webinar] Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 501
  • Last Modified:

Distribution of C/C++ library header files with library

I have a C++ library I am going to distribute upon completion.  Some of the header files for various classes have private variables which reference other code and require the developer to then include another header file in their code, or a cascade of header files if the referenced header is dependent on a host of others.

A good example of this would be a log file which uses an SqLite database as its storage mechanism.  The class opens the database once and it remains open until the class destructor is called.  Because the SqLite database object needs to remain open across calls to the methods of the class it is kept as a private class variable which requires #include <sqlite3.h> in the header file.

Is there a best practice or standard way of handling these sorts of situations?  I want to avoid items like forward declarations in the header file.  

I have thought about simply declaring such variables in the cpp body file, but it would not be encapsulated within the class in this approach, and I am not sure if there would be unintended  consequences of this approach.  

Another approach which does not seem elegant to me would be to create a second class to hold the private variables which then could be included in the cpp file without the need to put it in the header file.  Any approach I come up with seems to be clunky and non-standard.

Your help would be greatly appreciated.
Thanks.
0
edc
Asked:
edc
  • 3
  • 2
  • 2
  • +1
1 Solution
 
jkrCommented:
The trick would be to encapsulate these dependencies and only provide an interface to the users that does not require any 3rd party headers. I prefer pure virtual interfaces for that approach. E.g.
// database_if.h - that's what the user sees

IDatabase* CreateDB();

struct IDatabase {

  virtual bool Open() = 0;

  //...

  virtual void Close() = 0;
};

// sqlite3_database_if.h - that's what you use (pseudocode)

#include <sqlite3.h>

class Sqlite3Database : public IDatabase{

public:

  virtual bool Open()  { return sqlite3_open();}

  //...

  virtual void Close() { sqlite3_close();}

private:
  sqlite3_db the_db;
};

IDatabase* CreateDB() { return new Sqlite3Database;}

Open in new window

0
 
JimBeveridgeCommented:
I would recommend that you distribute a shared library (.dll in Windows or .so in Linux) and instead of a static library .lib. When you deliver a shared library, you compile it, so you don't need to worry about end-users linking to missing libraries or relying on header files. A shared library *is* the best practice for this situation.

Of course, if your intention is to deliver source code to your end-users, then there's really no workaround because they need all of the the headers and 3rd party libraries to build your source. There's no issue with SQLite because it's Public Domain, but just about anything else you use is going to be copyright, which means that you aren't allowed to distribute the header files to those libraries.
0
 
edcAuthor Commented:
@jkr - I think this solution would actually take care of several aspects of the library which have been puzzling me.  

One question that has come up in my mind - although I think I know the answer, I would like to verify with you.  Would I have to export ( __declspec(dllexport) ) the Sqlite3Database class as well as the IDatabase class?

Thanks for you advice and help.
0
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 
jkrCommented:
No, not at all. The only function that would have to be exported that way would be the 'factory', in the above

IDatabase* CreateDB();
0
 
sarabandeCommented:
it is good practice to use forward declarations in the header files as far as possible so you should not try to avoid them.

i would assume you then could have the include for sqllite in the cpp file only.

normally a database interface could be designed with pointers and references only which both could declared in the header using forward declaration.

Sara
0
 
edcAuthor Commented:
@jkr.  Thanks very much.  Your advice is always appreciated :o).

@sarabande.  Thank you for your thoughts.  Forward declarations are good practice, but for a few reasons I really wanted a different way to handle it.

@JimBeveridge.  Be not alarmed.  It is being distributed as a dll/so and I am not trying to pull any fast ones in regards to licensing of third parties.  I am curious though how you would approach using a C/C++ library without the header files.  Are you thinking __declspec(dllimport)?
0
 
JimBeveridgeCommented:
I agree with jkr. You don't want to publish header files that include any member data, so abstract interfaces are the way to go. However, it's a bit of a rat's nest from there, because the memory manager in the DLL is separate from the memory management in your app, so you can't pass around string or CString unless they are "const", and even that often won't work unless your DLL exactly matches the compiler versions, header file versions, etc. of the app. Nor can you "new" an object in the DLL and "delete" the object in the app.

All of which is why COM exists.
0
 
edcAuthor Commented:
Thank you everyone for providing your thoughts and experience.  I greatly appreciate it.
0

Featured Post

Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

  • 3
  • 2
  • 2
  • +1
Tackle projects and never again get stuck behind a technical roadblock.
Join Now