Solved

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

Posted on 2011-09-14
8
471 Views
Last Modified: 2012-06-21
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
Comment
Question by:edc
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 3
  • 2
  • 2
  • +1
8 Comments
 
LVL 86

Accepted Solution

by:
jkr earned 500 total points
ID: 36538879
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
 
LVL 7

Expert Comment

by:JimBeveridge
ID: 36539798
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
 
LVL 1

Author Comment

by:edc
ID: 36540331
@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
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 86

Expert Comment

by:jkr
ID: 36540365
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
 
LVL 34

Expert Comment

by:sarabande
ID: 36542103
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
 
LVL 1

Author Comment

by:edc
ID: 36542663
@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
 
LVL 7

Expert Comment

by:JimBeveridge
ID: 36543603
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
 
LVL 1

Author Closing Comment

by:edc
ID: 36543645
Thank you everyone for providing your thoughts and experience.  I greatly appreciate it.
0

Featured Post

Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Go is an acronym of golang, is a programming language developed Google in 2007. Go is a new language that is mostly in the C family, with significant input from Pascal/Modula/Oberon family. Hence Go arisen as low-level language with fast compilation…
Basic understanding on "OO- Object Orientation" is needed for designing a logical solution to solve a problem. Basic OOAD is a prerequisite for a coder to ensure that they follow the basic design of OO. This would help developers to understand the b…
The viewer will learn how to pass data into a function in C++. This is one step further in using functions. Instead of only printing text onto the console, the function will be able to perform calculations with argumentents given by the user.
The viewer will learn additional member functions of the vector class. Specifically, the capacity and swap member functions will be introduced.

756 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question