Click here to Skip to main content
Rate this: bad
good
Please Sign up or sign in to vote.
See more: C++
I've been writing a library for awhile now but I've never been able to figure out how to make it so users don't have to include the headers for all the dependencies I'm using in my library. The problem is that my classes need to store pointers and data types from various dependencies which have to be defined before use.
 
I've tried defining basic abstract versions of these data types before use which works for most types but there are a few that give me errors like type redefinition or what ever. I also tried to use an #ifdef to only define these variables within the header when I'm compiling my library but when I try to use my library without those variables defined in the header I get undefined behavior where random stuff just bugs out. So how the heck do I use third party libraries inside my library without needing to include their headers?
 
Say in my library header I have this class:
 
class __declspec( dllexport ) Myclass
{
public:
SDL_GLContext Context;
};
 
For anyone to include my header they would first need to include SDL. How can I store the context in my class without needing users of my library to include SDL?
Posted 19-Aug-12 17:31pm
Edited 11-Dec-12 10:15am
v3
Comments
Sergey Alexandrovich Kryukov at 20-Aug-12 0:01am
   
You are not hoping to get away without headers at all, aren't you?
If you could illustrate you idea on some minimal code sample (does not have to really work, it would be enough if it express your idea or requirements), it would be helpful.
--SA
Steven Batchelor at 20-Aug-12 3:03am
   
No, I have headers for my library but I don't want to have to include any headers from other dependencies.
enhzflep at 20-Aug-12 3:17am
   
in the example you've used here, I note particularly that you've got the data member as public. My memory is that the other libraries' functions get linked as needed into your library. You could test by removing your lirary's dependancies before building.
 
Your example above makes me wonder if your class may exposing more of it's internals than it should, leading to the need to declare certain types/functions as found in assorted header files.
Sergey Alexandrovich Kryukov at 20-Aug-12 3:28am
   
Thank you for clarification. Now you need to clarify the idea. Why would the user of your library use the declarations from other libraries? Did you try to wrap them in yours? What declarations would you like to pass to the users? One simple example based on one function per scenario could help...
--SA
Sergey Alexandrovich Kryukov at 20-Aug-12 3:42am
   
It looks like Solution 1 explains it all for you. For the record, please see also my last comment below...
I advise you to accept Solution 1 formally (green button).
--SA
Sergey Alexandrovich Kryukov at 20-Aug-12 3:31am
   
And why you can't simply include 3rd-party headers in your headers in the proper order? Your code sample does explain the situation, but it's nothing special. When your user includes your header, the declarations of the headers your code depends on are also compiled in the user's code without adding more includes. Is it not?
--SA

1 solution

Rate this: bad
good
Please Sign up or sign in to vote.

Solution 1

There are two methods to handle third-party includes:
 
a) put the #include of the third party header inside your own header
 
b) don't embed a full object of the third party, but just a pointer. In your case that would look like:
 
class SDL_GLContext;
 
class __declspec( dllexport ) Myclass
{
public:
    SDL_GLContext* pContext;
};
 
Then allocate the object inside your Myclass constructor. That way, you only need to make an advance declaration of the third-party class (first line in the code above).
 
There are two more techniques worth mentioning.
 
- on the Microsoft platform you can use #pragma directives inside your library code to save the users of your library the work of putting your library on the linker input list. For example
#pragma comment (lib, "MyLib.lib")
 
- use the so-called PIMPL technique (stands for pointer to pointer-to-implementation). This means: Declare just a single data member inside your class, which is a pointer to an implementation class. Then, in the .cpp file your declare an implementation class with all the member data you need. For example:
 
// in your .h file
class MyClassImpl;
 
class MyClass
{
public:
    // just declare those functions the external user is
    // allowed to see

private:
    MyClassImpl* m_pThis;
};
 
// in your .cpp file
class MyClassImpl
{
public:
    // here goes the implementation declaration of all the stuff
    // that should be hidded from the user
};
 
MyClass::MyClass()
{
     m_pThis = new MyClassImpl;
}
MyClass::~MyClass()
{
    delete m_pThis;
}
 
 
This is a nice technique to insolate your class and let the exterior only know the bare minimum about your class. Particularly: The external size of the class always stays the same (just the size of the pointer). That is very useful when your class is part of a library and the user allocates objects of your class in his own code. You may then add members to your implementation without having the user to recompile his entire code.
  Permalink  
v2
Comments
Sergey Alexandrovich Kryukov at 20-Aug-12 3:41am
   
Good reply, voted 5.
--SA
nv3 at 20-Aug-12 3:45am
   
Thanks Sergey!
Sergey Alexandrovich Kryukov at 20-Aug-12 3:43am
   
OP is advised to accept it formally.
--SA
Steven Batchelor at 20-Aug-12 3:48am
   
I remembered hearing about the PIMPL technique before but I could not remember the name nor how it worked. Thank you!
nv3 at 20-Aug-12 3:50am
   
Welcome!
CPallini at 11-Dec-12 16:18pm
   
5.
nv3 at 11-Dec-12 17:57pm
   
Thanks!

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

  Print Answers RSS
0 OriginalGriff 220
1 kbrandwijk 100
2 Richard MacCutchan 100
3 Vinay Mistry 70
4 Mukesh Bhagat 65
0 Sergey Alexandrovich Kryukov 9,040
1 OriginalGriff 8,121
2 CPallini 2,613
3 Richard MacCutchan 2,221
4 Abhinav S 1,928


Advertise | Privacy | Mobile
Web01 | 2.8.140827.1 | Last Updated 11 Dec 2012
Copyright © CodeProject, 1999-2014
All Rights Reserved. Terms of Service
Layout: fixed | fluid

CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100