Solved

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

Posted on 2011-09-14
8
467 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
  • 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
Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

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

 
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 33

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

Suggested Solutions

Title # Comments Views Activity
Exception thrown at 0x00007FFD5BC81F28 7 49
Create a path if not exists 7 87
How to Correctly derive class from CWinThread in MFC 4 64
Need some help with mailto 16 20
IntroductionThis article is the second in a three part article series on the Visual Studio 2008 Debugger.  It provides tips in setting and using breakpoints. If not familiar with this debugger, you can find a basic introduction in the EE article loc…
Many modern programming languages support the concept of a property -- a class member that combines characteristics of both a data member and a method.  These are sometimes called "smart fields" because you can add logic that is applied automaticall…
The viewer will learn how to use the return statement in functions in C++. The video will also teach the user how to pass data to a function and have the function return data back for further processing.
The viewer will learn how to user default arguments when defining functions. This method of defining functions will be contrasted with the non-default-argument of defining functions.

789 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