0

Is it considered a bad practice to expose different type names in API and not use types from the library itself?

If there is a library like this:

struct Internal {
    int first;
    float second;
};

int foo(struct Internal);

typedef enum {
    VALUE_1,
    VALUE_2
} INTERNAL_ENUM;

int bar(INTERNAL_ENUM);

It can be linked with header looking like this:

struct External {
    int first;
    float second;
};

int foo(struct External);

typedef enum {
    VALUE_1,
    VALUE_2
} EXTERNAL_ENUM;

int bar(EXTERNAL_ENUM);

In a situation where I create library that uses another library and I don't want that library to be exposed, is it considered impractical to use different type names for the API?

As the project is currently setup (I inherited it), there are two sets of data types, one maintained by me which mirrors the one used in some internal (statically linked) libraries. Code is more complex and full of bugs and I'm asking if my solution would be any better?

  • You can do whatever you want in your own library. It's a black box, so the fact that it uses some other library is normally irrelevant to the users. – Barmar Nov 10 '22 at 18:34
  • I'm aware of that, but I'm not sure if I would be doing the wrong thing by renaming types, not from the point of end users, but from my perspective and maintainability of the code. – Scaramouche Nov 10 '22 at 18:42

1 Answers1

0

In a situation where I create library that uses another library and I don't want that library to be exposed, is it considered impractical to use different type names for the API?

"Impractical" would be one word for it.

C's rules for type compatibility require structure types not only to have matching member lists, but also to have matching tags or to match in being tagless. Similarly for unions and enums. The rules also require all declarations of the same object or function to specify compatible types for it.*

This means that doing as you describe elicits undefined behavior. In this case, that includes not only undefined runtime behavior but undefined compile time behavior, too.

Given

application ---uses---> library 1 ---uses---> library 2

you have the choice of whether the headers of library 1 expose the data types of library 2 to application at all. If you choose for them to do, then for structure and union types you also have the choice of whether to expose them as opaque types. But if you want well defined behavior then you do not have the choice of re-tagging library 2's structure, union, or enum types for application consumption. Different tags yield incompatible types, as C uses the term.

As the project is currently setup (I inherited it), there are two sets of data types, one maintained by me which mirrors the one used in some internal (statically linked) libraries. Code is more complex and full of bugs and I'm asking if my solution would be any better?

I don't see what you think would be gained by continuing to "mirror" the data types of the internal libraries, but with different names. It sounds like that would make your problems worse in several ways, not better.

But you absolutely should come up with a way to avoid duplicating data type definitions. Arrange one way or another for all translation units involved to draw on the same definitions (or none at all) for all data types used. This is the purpose of headers.

Of course, this assumes that you are going to pass objects from the application level through library 1 to library 2, which certainly seems to be what you're describing. And that may be a good plan, but it is not your only alternative.


*This is about the types themselves, not type aliases declared via typedef.

John Bollinger
  • 160,171
  • 8
  • 81
  • 157
  • What troubles me is that there are already all the types defined in both libraries and there are conversions for enumerations and structs, function pointers etc are all just casted without checking while external API is just maintained by hand. – Scaramouche Nov 11 '22 at 12:25
  • That sure sounds messy and brittle, @Scaramouche, and I can understand why you would want to clean it up. But that does not change the fact that the specifics you proposed are not a valid way to perform such a cleanup (notwithstanding whether the result would in fact be cleaner). – John Bollinger Nov 11 '22 at 14:23