For the #define
values, you can declare these in your library's header file as external constants, similar to the functions.
extern const int LIBRARY_USERS_VALUE;
This forces the application code to declare the constant itself, which it can do with a #define
as well.
// Value used by the library, and elsewhere in this code.
#define ARBITRARY_NUMBER 69
// Define the constant declared in the library.
const int LIBRARY_USERS_VALUE = ARBITRARY_NUMBER;
As has been mentioned elsewhere, the struct
and typedef
are a little bit trickier. However, you can separate these into the bits required by the library and the bits that are used by the application. One technique, that is commonly used is to define a header that is required by the library that also has a 'generic' marker at the end that the application can fill in.
// Declare a type that points to a named, but undefined
// structure that the application code must provide.
typedef struct user_struct_tag* user_struct_pointer;
// Declare a type for a library structure, that refers to
// application data using the pointer to the undefined struct.
typedef struct
{
int userDataItemSize;
int userDataItemCount;
user_struct_pointer userDataPointer;
} library_type;
The application code then has to declare the structure (with the tag) itself.
// Define the structure referred to by the library in the application.
struct user_struct_tag
{
int dataLength;
char dataString[32];
};
// And typedef it if you need too.
typedef struct user_struct_tag user_data_type;
There are lots of other similar methods you can use, providing that your library has no need to know about the structure of the data in the application code. If it does, then the declaration of that structure needs to be available to the library at compile time. In these instances you would need to think about what the library is actually for, and whether you can need to use some kind of data abstraction for passing the information. For example, XML, TLV, etc.