I'm currently writing a C/C++ shared library which is planned to be an extension for another project. In the library, I need to call some functions and access some of the data structures of the original code. Clearly, the most obvious option would be to include the headers from the original code and let the user of the extension pass the pathes to the header files and build the library. In order to ease the build process, I thought about rewriting the required function declarations in a separate header file. Can this be considered good practice? What about libraries where the source code is not distributed? I would assume they use the same approach. Any help is appreciated!
-
1Read about design patterns "callback" and "listener".Piotr Siupa– Piotr Siupa2015-02-18 10:50:02 +00:00Commented Feb 18, 2015 at 10:50
-
With C++11 lambda functions could be very helpfulBasile Starynkevitch– Basile Starynkevitch2015-02-18 11:35:22 +00:00Commented Feb 18, 2015 at 11:35
-
My question was actually aiming at something different. I wanted to know if it is legitimate to write a custom header file for the shared library which declares only the functions the library requires. @hvd has already provided a useful answer. Sorry for not making myself clear enough.Marcel– Marcel2015-02-18 15:38:27 +00:00Commented Feb 18, 2015 at 15:38
2 Answers
Can this be considered good practice?
No. Shipping your own headers means you get no warning when the headers no longer match up with the library1. Structure types may get additional members, functions may change e.g. taking long instead of int like they used to, little things like that, that shouldn't affect users that use the provided headers, but will badly affect users that write their own.
The only time it makes sense is if the library promises ABI stability, that already-compiled third-party projects linked against an older version of the library will continue working. That's the exception, though, not the norm.
What about libraries where the source code is not distributed? I would assume they use the same approach.
If A links against B, and A is closed source, then A may still be recompiled by A's author against all versions of B.
If A links against B, and B is closed source, B still typically ships headers to allow users to make use of it.
If A links against B, and B is closed source, and doesn't ship headers, then typically, it is not designed to be linked against, and doing so anyway is a very bad idea. In a few rare scenarios, however, it does make sense, and shipping custom-written headers for B along with A may be a good idea.
1 When I write "library", I'm referring to the product associated with the headers. In the case of a plug-in, it's possible that the product associated with the headers would typically not be called a library, but the code using those headers would be.
2 Comments
You could use callbacks to separate main program from library.
For example, library which can calculate something. It could be data from any source, but here it is read from file:
library.h
struct FooCalc_S;
typedef struct FooCalc_S FooCalc_T;
typedef int (*Callback_T)(void * extra);
FooCalc_T * FooCalc_Create(Callback_T callback, void * extra);
int FooCalc_Run(FooCalc_T * fc); // Calls callback multiple times
main.c
#include "library.h"
int ReadFromFile(void * extra) {
FILE * fp = extra;
// Reads next entry from file
return result;
}
int main(void) {
FILE * fp = // Open file here
FooCalc_T * fc = FooCalc_Create(ReadFromFile, fp);
int foo = FooCalc_Run(fc);