2

I am trying to make a static library, where certain aspects of the library can be defined externally (outside the compiled library code).

For function definitions, I can compile the library without issue using extern void foo() declarations in the library, and then define the contents of foo() in the code referencing the static library.

I also want to make some #define values and typedef structs which are in the static library, editable externally.

If I remove the #defines or typedef structs declarations, then I am unable to compile the library.

All attempts at using extern also fail.

Is this possible ? If so, how do I do it ?

Regards, John.

Roxx
  • 3,738
  • 20
  • 92
  • 155
John
  • 55
  • 6
  • Why do you want to define structs outside of your library? So if you want to use them in your library it is possible to get some trouble if the user of your library does some wrong implementation of your struct. Further I do not know if it is possible. – Frodo Feb 09 '16 at 08:26
  • Thanks, yes I agree it is very possible to get into some trouble, but it is necessary in this application which connects to cameras of various image resolutions thus requiring various array allocations etc. I accept there are better ways of doing it without #defines, but the current library was originally designed for a fixed resolution camera and heavily depends on these #defines, so a method of externally editing is preferable to an extensive re-write of the library. – John Feb 10 '16 at 04:14

3 Answers3

1

#defines are handled at compile time, so you can't make these editable outside the (compiled) library.

typedefs and structs define a memory layout and offsets into these data types. These are handled at compile time to insert the right offsets in the compiled code to access the members and so are also handled at compile time and can't be editable outside the (compiled) library.

You can though pass the library functions void * pointers to your data structures, and pass the library functions to handle these externally defined data types. For example:

void genericSort(void *ArrayToSort, int (*cmp)(void *, void *));

Here, you pass the library function an array to sort and a function to compare two elements, without the library knowing anything about what this array holds.

Paul Ogilvie
  • 25,048
  • 4
  • 23
  • 41
0

See #define are pre-processor symbol, So while compiling it will be replaced by its original value. So it does not make any sense for making them extern in your library.

If you want some editing kind of access then use compiler time define for gcc you can use -D and -U


For typedef and structure definition, Using extern you can tell compile that it will be defined in some other file, but when you make library at that time that definition should be there. So what you want to do that its not possible.

Jeegar Patel
  • 26,264
  • 51
  • 149
  • 222
0

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.

Evil Dog Pie
  • 2,300
  • 2
  • 23
  • 46
  • Thanks. The const int approach works in terms of making the #define value editable, but unfortunately some of the typedefs have array containers which depend on these #defines, so the compiler correctly complains "array bound is not an integer constant". I guess there's no quick fix to this one without a re-structuring of the library. – John Feb 10 '16 at 05:02