Any alternatives to maintaining two separate structs with different names? - c

Say I have an existing C header that defines a struct with a generic name, inside generic.h like this:
typedef struct generic_name_s {
int count;
} generic_name_t;
I'd like to make generic_name_t type available to users of my SDK, but with a specific name instead of the generic one, so I don't pollute the namespace. I cannot simply use:
typedef generic_name_t specific_name_t;
since that would require including generic.h inside specific.h, and the namespace I'm exporting to only allows exporting headers that conform to the specific naming conventions (i.e. users of my library can only include specific.h and not generic.h).
One option is to maintain two separate copies of the struct, one with the generic and one with the specific name, but that seems error-prone. Is there a cleaner way to do this?
I've tried forward-declaring specific_name_t in specific.h:
typedef struct generic_name_s specific_name_t;
And then in specific.c, I #include "generic.h", which I thought would complete the definition of struct generic_name_s, but when a user of the library uses it (by doing "#include <specific.h>"), they still cannot access the struct members "variable has incomplete type".

Related

Library file (.a) where the contents of the structure changes

I am creating an algorithm in C that is confidential and cannot be shared with external customers. So, I decided to go with creating a library (.a) file which compiles my algorithm and lets others use it without modifying it. It basically alters the data of a variable within a structure. Now, the structure as such is visible externally (The structure is defined in a separate header file which is included in my .c file) and is generated based on user's configuration. But the said variable is always present within the structure - only remaining data is changed based on user's configuration.
The problem is that if the structure is not exactly the one I used to create the library file, the code fails.
So is there a way to create a library file to modify the data inside a structure, if the structure itself is not available in the beginning?
Any help is greatly appreciated...
Technically all structures you use must be character by character equal everywhere. If you have any difference between the same structure in two (or more) translation units that will lead to undefined behavior.
There are ways around that though, for example by using nested structures. For example you could create one structure to contain your private data, and then another structure whose first member is an instance of the first private structure.
For example something like this:
struct private_data
{
// TODO: The private members here
};
struct public_data
{
struct private_data private;
// TODO: The public members here
};
This is in effect similar to inheritance of an object-oriented language. A pointer to the public_data structure can be cast as a pointer to the private_data structure and passed to the functions that need it.
To keep the private data, well, private you could use opaque data types and opaque pointers:
// Forward declaration of the actual private data
struct actual_private_data;
// The "public" private structure
struct private_data
{
// Pointer to the actual private data
struct actual_private_data *private;
};
It's important to note that this only works for the private data used for the library. If the public data structure contains data that needs to be accessed by the library as well, you might want to rename the private_data structure and put the common data there. Note that this common data must be in all variants of the structure, it can't be auto-generated differently than what is used in the library.
If you are interested only in one data member of a structure,Then get the address of that variable in your confidential application and modify it's value.

How to have two structs with same type and name in different header files without conflicts?

I already have, say, a struct smallbox with two primitive variables (int identifier, int size) in it. This smallbox is part of higher structs that are used to build i.e. queues.
Now, I have in a part of my project an issue for which I came up with the solution to expand this smallbox, so it has another piece of information like int costs_to_send_it. While, I am not allowed to change my basis structs, is there a way to expand this struct in some fashion like methods overloading in java or so? Will I still be able to use all operation that I have on my higher structs while having the new struct smallbox with the new attribute inside instead of the old one?
This sentence determines the answer: “[Will] I still be able to use all operation that I have on my higher structs while having the new struct smallbox with color attribute inside instead of the old one?” The answer is no.
If the headers and routines involved were completely separate, there are some compiling and linking “games” you could play—compiling one set of source files with one definition of the structure and another set of source files with another definition of the structure and ensuring they never interacted in ways depending on the structure definition. However, since you ask whether the operations defined using one definition could be used with the alternate definition, you are compelling one set of code to use both definitions. (An alternate solution would be to engineer one source file to use different names for its routines under different circumstances, and then you could compile it twice, once for one definition of the structure and once for another, and then you could use the “same” operations on the different structures, but they would actually be different routines with different names performing the “same” operation in some sense.)
While you could define the structure differently within different translation units, when the structure or any type derived from it (such as a pointer to the structure) is used with a routine in a different translation unit, the type the routine is expecting to receive as a parameter must be compatible with the type that is passed to it as an argument, aside from some rules about signed types, adding qualifiers, and so on that do not help here.
For two structures to be compatible, there must be a one-to-one correspondence between their members, which must themselves be of compatible types (C 2018 6.2.7 1). Two structures with different numbers of members do not have a one-to-one correspondence.
is there a way to expand this struct in some fashion like methods
overloading in java or so?
In method overloading, the compiler chooses among same-named methods by examining the arguments to each invocation of a method of that name. Observe that that is an entirely localized decision: disregarding questions of optimization, the compiler's choice here affects only code generation for a single statement.
Where I still be able to use all operation
that I have on my higher structs while having the new struct smallbox
with color attribute inside instead of the old one?
I think what you're looking for is polymorphism, not overloading. Note well that in Java (and C++ and other the other languages I know of that support this) it is based on a type / subtype relationship between differently-named types. I don't know of any language that lets you redefine type names and use the two distinct types as if they were the same in any sense. Certainly C does not.
There are some alternatives, however. Most cleanly-conforming would involve creating a new, differently-named structure type that contains an instance of the old:
struct sb {
int id;
int size;
};
struct sb_metered {
struct sb box;
int cost;
}
Functions that deal in individual instances of these objects by pointer, not by value, can be satisfied easily:
int get_size(struct sb *box) {
return sb->size;
}
int get_cost(struct sb_metered *metered_box) {
return metered_box->cost;
}
int main() {
struct sb_metered b = { { 1, 17}, 42 };
printf("id: %d, size: %d, cost: %d\n",
b.id,
get_size(&b.box),
get_cost(&b));
}
Note that this does not allow you to form arrays of the supertype (struct sb) that actually contain instances of the subtype, nor to pass or return structure objects of the subtype by value as if they were objects of the supertype.

Incomplete type with size

I'm writing a C library, and have a struct that looks (roughly) like:
struct Obj {
char tag,
union {
int i,
void *v
} val
};
I do not want to expose the internals of this struct through the API, because users do not need to know the implementation and they could change in future versions. Users can interact with the struct via functions in the API.
I used incomplete types in the header for other, larger types in my API, which can only be accessed via pointer by the user. I do not want to restrict users to accessing Obj via pointer, as Obj will likely only be 16 bytes maximum.
I have not been able to use an incomplete type here, because I do not know of a way to expose only the size of the struct to users, without fields.
My question is:
Is there a way to expose a type with size only in C (no knowledge of the fields in the struct given to user), some other hack to accomplish what I want, or should I implement this in some completely different way?
Please comment if I haven't provided enough details or anything is unclear.
The standard pattern for this is to create a function which allocates the struct for the user:
struct Obj* obj_new(void) {
return malloc(sizeof(struct Obj));
}
Then just leave the type as incomplete in your public header.
Of course, if you really want to expose only the size, you could just create a function which returns sizeof(struct Obj). Obviously people can misuse it (e.g., hardcoding the value into their code as an "optimization" to avoid calling that function), but that's not on you. It is something that is done occasionally, usually to help facilitate inheritance.

What techniques/strategies do people use for building objects in C (not C++)?

I am especially interested in objects meant to be used from within C, as opposed to implementations of objects that form the core of interpreted languages such as python.
I tend to do something like this:
struct foo_ops {
void (*blah)(struct foo *, ...);
void (*plugh)(struct foo *, ...);
};
struct foo {
struct foo_ops *ops;
/* data fields for foo go here */
};
With these structure definitions, the code implementing foo looks something like this:
static void plugh(struct foo *, ...) { ... }
static void blah(struct foo *, ...) { ... }
static struct foo_ops foo_ops = { blah, plugh };
struct foo *new_foo(...) {
struct foo *foop = malloc(sizeof(*foop));
foop->ops = &foo_ops;
/* fill in rest of *foop */
return foop;
}
Then, in code that uses foo:
struct foo *foop = new_foo(...);
foop->ops->blah(foop, ...);
foop->ops->plugh(foop, ...);
This code can be tidied up with macros or inline functions so it looks more C-like
foo_blah(foop, ...);
foo_plugh(foop, ...);
although if you stick with a reasonably short name for the "ops" field, simply writing out the code shown originally isn't particularly verbose.
This technique is entirely adequate for implementing a relatively simple object-based designs in C, but it does not handle more advanced requirements such as explicitly representing classes, and method inheritance. For those, you might need something like GObject (as EFraim mentioned), but I'd suggest making sure you really need the extra features of the more complex frameworks.
Your use of the term "objects" is a bit vague, so I'm going to assume you're asking how to use C to achieve certain aspects of Object-Oriented Programming (feel free to correct me on this assumption.)
Method Polymorphism:
Method polymorphism is typically emulated in C using function pointers. For example if I had a struct that I used to represent an image_scaler ( something that takes an image and resizes it to new dimensions ), I could do something like this:
struct image_scaler {
//member variables
int (*scale)(int, int, int*);
}
Then, I could make several image scalers as such:
struct image_scaler nn, bilinear;
nn->scale = &nearest_neighbor_scale;
bilinear->scale = &bilinear_scale;
This lets me achieve polymorphic behavior for any function that takes in a image_scaler and uses it's scale method by simply passing it a different image_scaler.
Inheritance
Inheritance is usually achieved as such:
struct base{
int x;
int y;
}
struct derived{
struct base;
int z;
}
Now, I'm free to use derived's extra fields, along with getting all the 'inherited' fields of base. Additionally, If you have a function that only takes in a struct base. you can simply cast your struct dervied pointer into a struct base pointer with no consequences
Libraries such as GObject.
Basically GObject provides common way to describe opaque values (integers, strings) and objects (by manually describing the interface - as a structure of function pointers, basically correspoinding to a VTable in C++) - more info on the structure can be found in its reference
You would often also hand-implement vtables as in "COM in plain C"
As you can see from browsing all the answers, there are libraries,
function pointers, means of inheritance, encapsulation, etc., all
available (C++ was originally a front-end for C).
However, I have found that a VERY important aspect to software is
readability. Have you tried to read code from 10 years ago? As a
result, I tend to take the simplest approach when doing things like
objects in C.
Ask the following:
Is this for a customer with a deadline (if so, consider OOP)?
Can I use an OOP (often less code, faster to develop, more readable)?
Can I use a library (existing code, existing templates)?
Am I constrained by memory or CPU (for example Arduino)?
Is there another technical reason to use C?
Can I keep my C very simple and readable?
What OOP features do I really need for my project?
I usually revert to something like the GLIB API which allows me to
encapsulate my code and provides a very readable interface. If more
is needed, I add function pointers for polymorphism.
class_A.h:
typedef struct _class_A {...} Class_A;
Class_A* Class_A_new();
void Class_A_empty();
...
#include "class_A.h"
Class_A* my_instance;
my_instance = Class_A_new();
my_instance->Class_A_empty(); // can override using function pointers
Look at IJG's implementation. They not only use setjmp/longjmp for exception handling, they have vtables and everything. It is a well written and small enough library for you to get a very good example.
Similar to Dale's approach but a bit more of a footgun is how PostgreSQL represents parse tree nodes, expression types, and the like internally. There are default Node and Expr structs, along the lines of
typedef struct {
NodeTag n;
} Node;
where NodeTag is a typedef for unsigned int, and there's a header file with a bunch of constants describing all the possible node types. Nodes themselves look like this:
typedef struct {
NodeTag n = FOO_NODE;
/* other members go here */
} FooNode;
and a FooNode can be cast to a Node with impunity, because of a quirk of C structs: if two structs have identical first members, they can be cast to each other.
Yes, this means that a FooNode can be cast to a BarNode, which you probably don't want to do. If you want proper runtime type-checking, GObject is the way to go, though be prepared to hate life while you're getting the hang of it.
(note: examples from memory, I haven't hacked on the Postgres internals in a while. The developer FAQ has more info.)

How do I create an array of namespaces?

How can I create an array of namespaces? And because it seems like a long shot, if this is impossible, is there something similar to a namespace that can be made into an array?
The namespace, if it helps, contains these variables:
const int maxx=// depends on the particular namespace
// I need an array to go through each namespace and
// pick out the variable
const int maxy=// depends on particular namespace
//prgm is a class I made
prgm sector[maxx][maxy];
// another array of prgms. int is my shorthand of saying "depends on
// particular namespace", so is char.
prgm programs[int]={prgm1(int,int,char),prgm2(int,int,char)...
So any help would be welcome.
You could use reflection, but I think you should rethink your design.
I am not sure what language you are talking about, but in many (most?) languages, references to constants are replaced by the constant value at compile time. So they are no longer present at runtime and even reflection won't help.
You could create a class in each namespace that exposes the constants as (static) properties. Then you can use reflection to search the class in each namespace and obtain the constant values from the properties.
But, as mentioned by others, you should really rethink your design. Finally, namespaces are usually not accessable via reflection because they just extend the class names of the contained classes (and other stuff). Or is there a (non-esoteric) language that exposes namespaces as entities via reflection?
For .NET the reference for the System.Type.Namespace property states the following.
A namespace is a logical design-time naming convenience, used mainly to define scope in an application and organize classes and other types in a single hierarchical structure. From the viewpoint of the runtime, there are no namespaces.
Is this supposed to be C++? Sounds like you need to define a class, not a namespace, then create instances (objects) of that class and put them in an array.
So the sector variable gets tricky, since it is sized based on the value of maxx and maxy parameters that would be passed to the constructor of the class. You can take care of that problem by using a container class or a dynamically-allocated multi-dimensional array instead.
If you talk about C++, in there you can't pass namespaces as entities around. But you can do so with types, as type argument to templates. In this case, an MPL sequence could help together with MPL algorithms:
struct c1 { typedef int_<2> value_x; };
struct c2 { typedef int_<3> value_x; };
struct c3 { typedef int_<1> value_x; };
template<typename C> struct get_x : C::value_x { };
typedef vector<c1, c2, c3> scope_vec;
typedef max_element<
transform_view< scope_vec , get_x<_1> >
>::type iter;
You may then create your array like
prgm programs[deref< iter >::type::value];
Note that the search within that type-vector happens at compile time. So the value of the array is determined at compile time either.

Resources