The question is based on a design pattern solution easily doable in other languages but difficult to implement in C. The narrowed down code is below.
Building on this answer, I'm trying to find a solution for the dynamically generated values in an anonymous function.
Excerpt from the answer:
int (*max)(int, int) =
({
int __fn__ (int x, int y) { return x > y ? x : y; }
__fn__;
});
Static Library Code
struct Super{
}
void add(struct Super *(*superRef)()) {
// cache the reference (in some linked list)
// later at some point when an event occurs.
struct Super *super = superRef(); // instantiate and use it.
}
Client Code linked: User of the Library Code
struct Sub{
struct Super *super;
}
add(({
struct Sub __fn__() { return malloc(sizeof(struct Sub)); } // error
__fn__;
}));
Error:
error: passing 'void' to parameter of incompatible type 'struct Sub *(*)()
As per the request for clarification, think of the receiving function in a static library file receiving references to the structure objects (non-instantiated). The lib receives this object from the client code.
Secondly the client or static library library doesn't instantiate the received structure reference right away. Later when there's a notification in the system, the structure reference is called to instantiate and execute the rest of the stuff.
I repeat, the specific requirement is to hold non-instantiated references to the structures passed by users of the library (client code).
Summary
Basically a Runner that receives pointer to a polymorphic factory method which it caches and later calls to instantiate and executes when an event occurs.
The correct order is:
learn C
do magic
It just will not work in the other way. ({}) does not bend the semantics for you. If your add expects a function which returns struct Super*, it will not work with struct Sub, not even if you put the missing * there.
This just works on TutorialsPoint:
#include <stdio.h>
#include <stdlib.h>
int max(int a,int b){
if(a>b)
return a;
return b;
}
struct Super{};
void add(struct Super *(*superRef)()) {
struct Super *(*secretStorage)()=superRef;
/* ... */
struct Super *super = secretStorage();
/* ... */
free(super);
printf("Stillalive\n");
}
int main()
{
printf("Hello, World!\n");
int (*myMax)(int,int); // <-- that is a function pointer
myMax=max; // <-- set with oldschool function
printf("%d\n",myMax(1,2));
myMax = ({ // <-- set with fancy magic
int __fn__ (int x, int y) { return x < y ? x : y; }
__fn__;
});
printf("%d - intentionally wrong\n",myMax(1,2));
add(
({
struct Super* fn(){
printf("Iamhere\n");
return malloc(sizeof(struct Super));
}
fn;}));
printf("Byfornow\n");
return 0;
}
Created a small library project with anonymous magic embedded in anonymous magic and heap allocation. It does not make much sense, but it works:
testlib.h
#ifndef TESTLIB_H_
#define TESTLIB_H_
struct Testruct{
const char *message;
void (*printmessage)(const char *message);
};
extern struct Testruct *(*nonsense())();
#endif
testlib.c
#include "testlib.h"
#include <stdio.h>
#include <stdlib.h>
const char *HELLO="Hello World\n";
struct Testruct *(*nonsense())(){
return ({
struct Testruct *magic(){
struct Testruct *retval=malloc(sizeof(struct Testruct));
retval->message=HELLO;
retval->printmessage=({
void magic(const char *message){
printf(message);
}
magic;
});
return retval;
}
magic;
});
}
test.c
#include "testlib.h"
#include <stdio.h>
#include <stdlib.h>
int main(){
struct Testruct *(*factory)()=nonsense();
printf("Alive\n");
struct Testruct *stuff=factory();
printf("Alive\n");
stuff->printmessage(stuff->message);
printf("Alive\n");
free(stuff);
printf("Alive\n");
return 0;
}
I followed the steps in https://www.cprogramming.com/tutorial/shared-libraries-linux-gcc.html for building an running it (practically 3 gcc calls: gcc -c -Wall -Werror -fpic testlib.c, gcc -shared -o libtestlib.so testlib.o, gcc -L. -Wall -o test test.c -ltestlib and a bit of fight with LD_LIBRARY_PATH)
The code shown in the question is not standard C, but the GNU C variant that GCC supports. Unfortunately, there does not seem to be a gnu-c tag, to correctly specify the variant of C involved.
Furthermore, the use case seems to rely on shoehorning specific type of object-oriented paradigm into a C library interface. This is horrible, because it involves assumptions and features C simply does not have. There is a reason why C (and GNU-C) and C++ and Objective-C are different programming languages.
The simple answer to "functions returning dynamically allocated values" where the type of the value is opaque to the library, is to use void *, and for function pointers, (void *)(). Note that in POSIX C, void * can also hold a function pointer.
The more complex answer would describe how libraries like GObject support object-oriented paradigms in C.
In practice, especially in POSIX C, using a type tag (usually int, but can be any other type) and an union, one can implement polymorphic structures, based on an union of structures with all having that type tag as the same first element. The most common example of such functionality is struct sockaddr.
Basically, your header file defines one or more structures with the same initial member, for example
enum {
MYOBJECT_TYPE_DOUBLE,
MYOBJECT_TYPE_VOID_FUNCTION,
};
struct myobject_double {
int type; /* MYOBJECT_TYPE_DOUBLE */
double value;
};
struct myobject_void_function {
int type; /* MYOBJECT_TYPE_VOID_FUNCTION */
void (*value)();
};
and at the end, an union type, or a structure type with an anonymous union (as provided by C11 or GNU-C), of all the structure types,
struct myobject {
union {
struct { int type; }; /* for direct 'type' member access */
struct myobject_double as_double;
struct myobject_void_function as_void_function;
};
};
Note that technically, wherever that union is visible, it is valid to cast any pointer of any of those structure types to another of those structure types, and access the type member (see C11 6.5.2.3p6). It is not necessary to use the union at all, it suffices for the union to be defined and visible.
Still, for ease of maintenance (and to avoid arguments with language lawyer wannabes who did not read that paragraph in the C standard), I do recommend using the structure containing the anonymous union as the "base" type in the library interface.
For example, the library might provide a function to return the actual size of some object:
size_t myobject_size(struct myobject *obj)
{
if (obj)
switch (obj->type) {
case MYOBJECT_TYPE_DOUBLE: return sizeof (struct myobject_double);
case MYOBJECT_TYPE_VOID_FUNCTION: return sizeof (struct myobject_void_function);
}
errno = EINVAL;
return 0;
}
It seems to me OP is trying to implement a factory pattern, where the library function provides the specification (class in OOP) for the object created, and a method to produce those objects later.
The only way in C to implement dynamic typing is via the kind of polymorphism I show above. This means that the specification for the future objects (again, class in OOP) must be an ordinary object itself.
The factory pattern itself is pretty easy to implement in standard C. The library header file contains for example
#include <stdlib.h>
/*
* Generic, application-visible stuff
*/
struct any_factory {
/* Function to create an object */
void *(*produce)(struct any_factory *);
/* Function to discard this factory */
void (*retire)(struct any_factory *);
/* Flexible array member; the actual
size of this structure varies. */
unsigned long payload[];
};
static inline void *factory_produce(struct any_factory *factory)
{
if (factory && factory->produce)
return factory->produce(factory);
/* C has no exceptions, but does have thread-local 'errno'.
The error codes do vary from system to system. */
errno = EINVAL;
return NULL;
}
static inline void factory_retire(struct any_factory *factory)
{
if (factory) {
if (factory->retire) {
factory->retire(factory);
} else {
/* Optional: Poison function pointers, to easily
detect use-after-free bugs. */
factory->produce = NULL;
factory->retire = NULL; /* Already NULL, too. */
/* Free the factory object. */
free(factory);
}
}
}
/*
* Library function.
*
* This one takes a pointer and size in chars, and returns
* a factory object that produces dynamically allocated
* copies of the data.
*/
struct any_factory *mem_factory(const void *, const size_t);
where factory_produce() is a helper function which invokes the factory to produce one object, and factory_retire() retires (discards/frees) the factory itself. Aside from the extra error checking, factory_produce(factory) is equivalent to (factory)->produce(factory), and factory_retire(factory) to (factory)->retire(factory).
The mem_factory(ptr, len) function is an example of a factory function provided by a library. It creates a factory, that produces dynamically allocated copies of the data seen at the time of the mem_factory() call.
The library implementation itself would be something along the lines of
#include <stdlib.h>
#include <string.h>
#include <errno.h>
struct mem_factory {
void *(*produce)(struct any_factory *);
void (*retire)(struct any_factory *);
size_t size;
unsigned char data[];
};
/* The visibility of this union ensures the initial sequences
in the structures are compatible; see C11 6.5.2.3p6.
Essentially, this causes the casts between these structure
types, for accessing their initial common members, valid. */
union factory_union {
struct any_factory any;
struct mem_factory mem;
};
static void *mem_producer(struct any_factory *any)
{
if (any) {
struct mem_factory *mem = (struct mem_factory *)any;
/* We return a dynamically allocated copy of the data,
padded with 8 to 15 zeros.. for no reason. */
const size_t size = (mem->size | 7) + 9;
char *result;
result = malloc(size);
if (!result) {
errno = ENOMEM;
return NULL;
}
/* Clear the padding. */
memset(result + size - 16, 0, 16);
/* Copy the data, if any. */
if (mem->size)
memcpy(result, mem->data, size);
/* Done. */
return result;
}
errno = EINVAL;
return NULL;
}
static void mem_retirer(struct any_factory *any)
{
if (any) {
struct mem_factory *mem = (struct mem_factory *)any;
mem->produce = NULL;
mem->retire = NULL;
mem->size = 0;
free(mem);
}
}
/* The only exported function:
*/
struct any_factory *mem_factory(const void *src, const size_t len)
{
struct mem_factory *mem;
if (len && !src) {
errno = EINVAL;
return NULL;
}
mem = malloc(len + sizeof (struct mem_factory));
if (!mem) {
errno = ENOMEM;
return NULL;
}
mem->produce = mem_producer;
mem->retire = mem_retirer;
mem->size = len;
if (len > 0)
memcpy(mem->data, src, len);
return (struct any_factory *)mem;
}
Essentially, the struct any_factory type is actually polymorphic (not in the application, but within the library only). All its variants (struct mem_factory here) has the two initial function pointers in common.
Now, if we examine the code above, and consider the factory pattern, you should realize that the function pointers provide very little of value: you could just use the polymorphic type I showed earlier in this answer, and have the inline producer and consumer functions call subtype-specific internal functions based on the type of the factory. factory.h:
#ifndef FACTORY_H
#define FACTORY_H
#include <stdlib.h>
struct factory {
/* Common member across all factory types */
const int type;
/* Flexible array member to stop applications
from declaring static factories. */
const unsigned long data[];
};
/* Generic producer function */
void *produce(const struct factory *);
/* Generic factory discard function */
void retire(struct factory *);
/*
* Library functions that return factories.
*/
struct factory *mem_factory(const void *, const size_t);
#endif /* FACTORY_H */
and factory.c:
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "factory.h"
enum {
INVALID_FACTORY = 0,
/* List of known factory types */
MEM_FACTORY,
/* 1+(the highest known factory type) */
NUM_FACTORY_TYPES
};
struct mem_factory {
int type;
size_t size;
char data[];
};
/* The visibility of this union ensures the initial sequences
in the structures are compatible; see C11 6.5.2.3p6.
Essentially, this causes the casts between these structure
types, for accessing their initial common members, valid. */
union all_factories {
struct factory factory;
struct mem_factory mem_factory;
};
/* All factories thus far implemented
are a single structure dynamically
allocated, which makes retiring simple.
*/
void retire(struct factory *factory)
{
if (factory &&
factory->type > INVALID_FACTORY &&
factory->type < NUM_FACTORY_TYPES) {
/* Poison factory type, to make it easier
to detect use-after-free bugs. */
factory->type = INVALID_FACTORY;
free(factory);
}
}
char *mem_producer(struct mem_factory *mem)
{
/* As a courtesy for users, return the memory
padded to a length multiple of 16 chars
with zeroes. No real reason to do this. */
const size_t size = (mem->size | 7) + 9;
char *result;
result = malloc(size);
if (!result) {
errno = ENOMEM;
return NULL;
}
/* Clear padding. */
memset(result + size - 16, 0, 16);
/* Copy data, if any. */
if (mem->size)
memcpy(result, mem->data, mem->size);
return result;
}
/* Generic producer function.
Calls the proper individual producers.
*/
void *factory_producer(struct factory *factory)
{
if (!factory) {
errno = EINVAL;
return NULL;
}
switch (factory->type) {
case mem_factory:
return mem_producer((struct mem_factory *)factory);
default:
errno = EINVAL;
return NULL;
}
}
/* Library functions that return factories.
*/
struct factory *mem_factory(const void *ptr, const size_t len)
{
struct mem_factory *mem;
if (!ptr && len > 0) {
errno = EINVAL;
return NULL;
}
mem = malloc(len + sizeof (struct mem_factory));
if (!mem) {
errno = ENOMEM;
return NULL;
}
mem->type = MEM_FACTORY;
mem->size = len;
if (len > 0)
memcpy(mem->data, ptr, len);
return (struct factory *)mem;
}
If we look at standard C and POSIX C library implementations, we'll see that both of these approaches are used.
The standard I/O FILE structure often contains function pointers, and the fopen(), fread(), fwrite(), etc. functions are just wrappers around these. This is especially the case if the C library supports an interface similar to GNU fopencookie().
POSIX.1 socket, especially the struct sockaddr type, is the original prototype for the polymorphic structure shown first in this answer. Because their interface does not support anything similar to fopencookie() (that is, overriding the implementation of e.g. send(), recv(), read(), write(), close()), there is no need for the function pointers.
So, please do not ask which one is more suitable, as both are very commonly used, and it very much depends on minute details.. In general, I prefer the one that yields a simpler implementation providing all the necessary functionality.
I have personally found that it is not that useful to worry about future use cases without practical experience and feedback first. Rather than trying to create the end-all, best-ever framework that solves all future problems, the KISS principle and the Unix philosophy seem to yield much better results.
(Quoting your accepted answer to yourself)
Secondly a pointer to a parent struct can't receive a pointer to it's derived type (Embedded parent struct) so I can't do much there. I tried using void * but perhaps a solution might exists using memory address and then access some member of the struct without casting to specific types. I'll ask that in another question.
This is yet another pointer that one should learn the basics first. The thing you miss is called 'forward declaration':
struct chicken; // here we tell the compiler that 'struct chicken' is a thing
struct egg{
struct chicken *laidby; // while the compiler knows no details about 'struct chicken',
// its existence is enough to have pointers for it
};
struct chicken{ // and later it has to be declared properly
struct egg *myeggs;
};
What I'm missing is the ability to call the super method from the overridden run method in some way?
These are not methods and there is no override. In your code no OOP happens, C is a procedural programming language. While there are OOP extensions for C, you really should not go for them without knowing C basics.
First community told me that anonymous functions are not part of C, so the alternate suggestion is to use named functions and pointer to it.
Secondly a pointer to a parent struct can't receive a pointer to it's derived type (Embedded parent struct) so I can't do much there. I tried using void * but perhaps a solution might exists using memory address and then access some member of the struct without casting to specific types. I'll ask that in another question.
What I'm missing is the ability to call the super method from the overridden run method in some way?
src/super.h
struct Super {
void (*run)();
};
struct Super *newSuper();
src/super.c
static void run() {
printf("Running super struct\n");
}
struct Super *newSuper() {
struct Super *super = malloc(sizeof(struct Super));
super->run = run;
return super;
}
src/Runner.h
struct Runner {
void (*addFactoryMethod)(struct Super *(*ref)());
void (*execute)();
};
struct Runner *newRunner();
src/runner.c
struct Super *(*superFactory)();
void addFactoryMethod(struct Super *(*ref)()) {
superFactory = ref;
}
static void execute() {
struct Super *sup = superFactory(); // calling cached factory method
sup->run();
}
struct Runner *newRunner() {
struct Runner *runner = malloc(sizeof(struct Runner));
runner->addFactoryMethod = addFactoryMethod;
runner->execute = execute;
return runner;
}
test/runner_test.c
void anotherRunMethod() {
printf("polymorphism working\n");
// how can i've the ability to call the overridden super method in here?
}
struct Super *newAnotherSuper() {
struct Super *super = malloc(sizeof(struct Super));
super->run = anotherRunMethod;
return super;
}
void testSuper() {
struct Runner *runner = newRunner();
runner->addFactoryMethod(&newAnotherSuper);
runner->execute();
}
int main() {
testSuper();
return 0;
}
Related
We have an anonymous type, typedefed to void *, which is the handle for an API (all code in C11). It is deliberately void * as what it is pointing to changes depending on the platform we are compiled for and we also don't want the application to try dereferencing it. Internally we know what it should be pointing to and we cast it appropriately. This is fine, the code is public, we've been using it for years, it cannot be changed.
The problem is that we now need to introduce another one of these, and we don't want the user to get the two confused, we want the compiler to throw an error if the wrong handle is passed to one of our functions. However, all of the versions of all of the C compilers I have tried so far (GCC, Clang, MSVC) don't care; they know that the underlying type is void * and so anything goes (this is with -Wall and -Werror). Putting it another way, our typedef has not achieved anything, we might as well have just used void *. I have also tried Lint and CodeChecker, who also don't seem to care (though you could probably question my configurations for these). Note that I am not able to use -Wpedantic as we include third party code where that wouldn't fly.
I have tried making the new thing a specific typedefed pointer rather than a void * but that doesn't entirely fix things as the compiler is still happy for the caller to pass that new specific typedefed pointer into the existing functions that are expecting the existing handle typedef.
Is there (a) a way to construct a new anonymous handle such that the compiler will not allow it to be passed to the existing functions or (b) a checker that we can apply to pick the problem up, at least in our own use of these APIs?
Here is some code to illustrate the problem:
#include <stdlib.h>
typedef struct {
int contents;
} existingThing_t;
typedef void *anonExistingHandle_t;
typedef struct {
char contents[10];
} newThing_t;
typedef void *anonNewHandle_t;
typedef newThing_t *newHandle_t;
static void functionExisting(anonExistingHandle_t handle)
{
existingThing_t *pThing = (existingThing_t *) handle;
// Perform the function
(void) pThing;
}
static void functionNew(anonNewHandle_t handle)
{
newThing_t *pThing = (newThing_t *) handle;
// Perform a new function
(void) pThing;
}
int main() {
anonExistingHandle_t existingHandle = NULL;
anonNewHandle_t newHandleA = NULL;
newHandle_t newHandleB = NULL;
functionExisting(existingHandle);
functionNew(newHandleA);
// These should result in a compilation error
functionExisting(newHandleA);
functionNew(existingHandle);
functionExisting(newHandleB);
return 0;
}
Is there (a) a way to construct a new anonymous handle such that the compiler will not allow it to be passed to the existing functions
Yes, use a type that can't be implicitly converted to void *. Use a structure.
typedef struct {
struct newThing_s *p;
} anonNewHandle_t;
Anyway, your design is just flawed and disables all static compiler checks. Do not use void *, instead use structures or structures with void * inside, to enable compile checks. Research how the very, very standard FILE * works. FILE is not void.
Do not use typedef pointers. They are very confusing. https://wiki.sei.cmu.edu/confluence/display/c/DCL05-C.+Use+typedefs+of+non-pointer+types+only
I suggest rewriting your library so that you do not use void * and do not use typedef pointers.
The design, may look like the following:
// handle.h
struct handle_s;
typedef struct {
struct handle_s *p;
} handle_t;
handle_t handle_init(void);
void handle_deinit(handle_t t);
void handle_do_something(handle_t t);
// handle.c
struct handle_s {
int the_stuff_you_need;
};
handle_t handle_init(void) {
return (handle_t){
.p = calloc(1, sizeof(struct handle_s))
};
}
void handle_do_something(handle_t h) {
struct hadnle_s *t = h->p;
// etc.
}
// anotherhandle.h
// similar to above
typedef struct {
struct anotherhandle_s *p;
} anotherhandle_t;
void anotherhandle_do_something(anotherhandle_t h);
// main
int main() {
handle_t h = handle_new();
handle_do_something(h);
handle_free(h);
anotherhandle_do_something(h); // compiler error
}
Not entirely sure my question title describes what I want to do, but couldn't think how better to word it!! I'm using C, and perhaps the pseudocode below will describe what I'm trying to do:
typedef struct obj
{
char *str1;
char *str2;
char *str3;
} object;
/* global variable */
object *glob;
void black_box_function(local, member) ????
{
/* Do something with glob->member and local->member */
}
void main()
{
object *ob1, *ob2;
/* Initialise glob, ob1 and ob2 somewhere */
black_box_function(ob1, str1);
black_box_function(ob2, str3);
}
Hopefully, you can see what I'm trying to do. I have a "black-box" function that will do something with a particular member, and I need to be able to tell the black-box function which member to use.
I don't want to just pass the member directly to the function, like in this code, as that won't fit into the rest of my code easily.
black_box_function(ob1->member, glob->member)
You could do the following magic (with GCC extensions):
#define black_box(local, member) black_box_function((local), __builtin_offsetof(object, member))
void black_box_function(object *local, int offset)
{
char *lmember = ((void *)local) + offset;
char *gmember = ((void *)global) + offset;
/* do stuff */
}
However, you must know in advance the type of your members. Keep in mind that C is not a dynamically typed language, so you have no runtime introspection at all.
EDIT: You can implement offsetof() functionality without resorting to GCC extensions, like this:
#define offsetof(type, field) ((int) (unsigned long) &((type *) 0)->field)
Perhaps you could create accessor functions for your struct and pass those accessors as function pointer arguments instead of passing the members directly
typedef struct
{
int a;
int b;
} foo;
typedef int* (*accessor)(foo*);
int* get_a(foo* f) { return &f->a; }
int* get_b(foo* f) { return &f->b; }
void black_box_function(foo* object, accessor fn)
{
int* p = fn(object);
}
int main(void)
{
foo bar1;
foo bar2;
black_box_function(&bar1, get_a);
black_box_function(&bar2, get_b);
return 0;
}
Since all are char*, you can redefine the struct like:
typedef struct obj
{
char **str; // Array of c
} object;
Then you can send the index of str from main which you want work with:
black_box_function(obj1, index)
So you can it like obj1->str[i] in your blackbox.
Btw, black-box_function will not compile.
On a side note: A little more info/code on your blackbox function and compilable code would give a better picture of what you are trying to do.
In C, you can define structures to hold an assortment of variables;
typedef struct {
float sp;
float K; // interactive form - for display only
float Ti; // values are based in seconds
float Td;
} pid_data_t;
But lets say that K, Ti, and Td should never be set publicly, and should only be used for storing the values after they have been manipulated. So, I want these values not to be updated by;
pid_data_t = pid_data;
pid_data.K = 10; // no good! changing K should be done via a function
I want them to be set via a function;
int8_t pid_set_pid_params(float new_K_dash, float new_Ti_dash,
float new_Td_dash)
{
… // perform lots of things
pid_data->K = new_K_dash;
pid_data->Ti = new_Ti_dash;
pid_data->Td = new_Td_dash;
}
Any thoughts on this? I know C++ uses like a get/set property, but was wondering what people might do on C.
Your public interface should only offer an opaque pointer (maybe DATA*, or data_handle), as well as handler functions create_data(), set_data_value(), read_data_value(), free_data(), etc., which operate on the opaque pointer.
Much like FILE*.
Just don't give your clients the internal header files :-)
// library.h
typedef struct data_t * data_handle;
data_handle create_data();
void free_data(data_handle);
Private implementation (don't ship):
#include "library.h"
struct data_t
{
/* ... */
};
data_handle create_data() { return malloc(sizeof(struct data_t)); }
void free_data(data_handle h) { free(h); }
/* etc. etc. */
in C, by convention....
for OO C like this...
I'd have a pid_data_create(&data) // initializes your struct
and pid_data_set_proportional_gain(&data, 0.1);
etc...
so basically achieving a C++ ish class... prefix all functions with the "class" / "struct" name and always pass the struct * as the first parameter.
also, it should store function pointers for polymorphisim, and you shouldn't call those function pointers directly, again, have a function that takes your struct as a parameter, and then the can make the function pointer call (can check for nulls, fake inheritance/virtual functions, and other stuff)
The canonical way to do this is by using a combination of opaque pointers and public structs, along with allocators, getters and setters for the private elements. About along these lines:
foo.h
typedef struct Foo {
/* public elements */
} Foo;
Foo *new_Foo(void);
void Foo_something_opaque(Foo* foo);
foo.c
#include "foo.h"
typedef struct Private_Foo_ {
struct Foo foo;
/* private elements */
} Private_Foo_;
Foo *new_Foo(void)
{
Private_Foo_ *foo = malloc(sizeof(Private_Foo_));
/* initialize private and public elements */
return (Foo*) foo;
}
void Foo_something_opaque(Foo *foo)
{
Private_Foo_ *priv_foo = (Private_Foo_*) foo;
/* do something */
}
This woks, because C guarantees, that the address of a struct variable always is equal to the address of the very first struct element. We can use this to have a Private_Foo_ struct, containing a public Foo at the beginning, giving out pointers to the whole thing, with the compilation units not having access to the Private_Foo_ struct defintion just seeing some memory without any context.
It should be noted that C++ works quite similar behind the curtains.
Update
As KereekSB pointed out, this will break if used in a array.
I say: Then don't make Foo f[], however tempting, but make an arrays of pointers to Foo: Foo *f[].
If one really insists on using it in arrays do the following:
foo_private.h
typedef struct Private_Foo_ {
/* private elements */
} Private_Foo_;
static size_t Private_Foo_sizeof(void) { return sizeof(Private_Foo_); }
foo_private.h is written in a way, that it can be compiled into an object file. Use some helper program to link it and use the result of Private_Foo_sizeof() to generate the actual, plattform dependent foo.h from some foo.h.in file.
foo.h
#include
#define FOO_SIZEOF_PRIVATE_ELEMENTS <generated by preconfigure step>
typedef struct Foo_ {
/* public elements */
char reserved[FOO_SIZEOF_PRIVATE_ELEMENTS];
} Foo;
Foo *new_Foo(void);
void Foo_something_opaque(Foo* foo);
foo.c
#include "foo.h"
#include "foo_private.h"
Foo *new_Foo(void)
{
Foo *foo = malloc(sizeof(Foo));
/* initialize private and public elements */
return (Foo*) foo;
}
void Foo_something_opaque(Foo *foo)
{
Private_Foo_ *priv_foo = (Private_Foo_*) foo.reserved;
/* do something */
}
IMHO this is really messy. Now I'm a fan of smart containers (unfortunately there's no standard container library for C). Anyway: In such a container is creates through a function like
Array *array_alloc(size_t sizeofElement, unsigned int elements);
void *array_at(Array *array, unsigned int index);
/* and all the other functions expected of arrays */
See the libowfaw for an example of such an implementation. Now for the type Foo it was trivial to provide a function
Array *Foo_array(unsigned int count);
Object orientation is a way of thinking and modelling, data encapsulation where struct data should not be modified directly by the user can be implemented this way:
my_library.h
#ifndef __MY_LIBRARY__
#define __MY_LIBRARY__
typedef void MiObject;
MyObject* newMyObject();
void destroyMyObject(MyObject*)
int setMyObjectProperty1(MyObject*,someDataType1*);
/*Return a pointer to the data/object, classic pass by value */
someDataType1* getMyObjectProperty2Style1(MyObject*);
int setMyObjectProperty2(MyObject*,someDataType2*);
/* The data/object is passed through reference */
int getMyObjectProperty2Style2(MyObject*,someDataType2**);
/* Some more functions here */
#endif
my_library.c
struct _MyHiddenDataType{
int a;
char* b;
..
..
};
MyObject* newMyObject(){
struct _MyHiddenData* newData = (struct _MyHiddenData*)malloc(sizeof(struct _MyHiddenData);
//check null, etc
//initialize data, etc
return (MyObject*)newData;
}
int setMyObjectProperty1(MyObject* object,someDataType1* somedata){
struct _MyHiddenData* data = (struct _MyHiddenData*)object;
//check for nulls, and process somedata
data->somePropery=somedata;
}
someDataType1* getMyObjectProperty2Style1(MyObject*){
struct _MyHiddenData* data = (struct _MyHiddenData*)object;
//check for nulls, and process somedata
return data->someProperty;
}
/* Similar code for the rest */
And this way you have encapsulated the struct properties as if they were private. On the same manner static functions inside my_libray.c would behave as private functions. Get a good look at C and you'll see, that your imagination is the limit to what you can do.
Can structures contain functions?
No, but they can contain function pointers.
If your intent is to do some form of polymorphism in C then yes, it can be done:
typedef struct {
int (*open)(void *self, char *fspec);
int (*close)(void *self);
int (*read)(void *self, void *buff, size_t max_sz, size_t *p_act_sz);
int (*write)(void *self, void *buff, size_t max_sz, size_t *p_act_sz);
// And data goes here.
} tCommClass;
The typedef above was for a structure I created for a general purpose communications library. In order to initialise the variable, you would:
tCommClass *makeCommTcp (void) {
tCommClass *comm = malloc (sizeof (tCommClass));
if (comm != NULL) {
comm->open = &tcpOpen;
comm->close = &tcpOpen;
comm->read = &tcpOpen;
comm->write = &tcpWrite;
}
return comm;
}
tCommClass *makeCommSna (void) {
tCommClass *comm = malloc (sizeof (tCommClass));
if (comm != NULL) {
comm->open = &snaOpen;
comm->close = &snaOpen;
comm->read = &snaOpen;
comm->write = &snaWrite;
}
return comm;
}
tCommClass *commTcp = makeCommTcp();
tCommClass *commSna = makeCommSna();
Then, to call the functions, something like:
// Pass commTcp as first params so we have a self/this variable
// for accessing other functions and data area of object.
int stat = (commTcp->open)(commTcp, "bigiron.box.com:5000");
In this way, a single type could be used for TCP, SNA, RS232 or even carrier pidgeons, with exactly the same interface.
edit Cleared up ambiguity with the use of 'data types'
Not in C. struct types can only contain data.
From Section 6.7.2.1 of the ISO C99 Standard.
A structure or union shall not contain a member with incomplete or function type (hence,
a structure shall not contain an instance of itself, but may contain a pointer to an instance
of itself), except that the last member of a structure with more than one named member
may have incomplete array type; such a structure (and any union containing, possibly
recursively, a member that is such a structure) shall not be a member of a structure or an
element of an array.
No, you cannot. A structure cannot contain a declaration of a function but they can contain a definition of a function. A structure can only contain data types, pointers, pointers to different function. You can make a pointer to a function and then access from the structure.
#include<iostream>
#include<cstring>
using namespace std;
struct full_name
{
char *fname;
char *lname;
void (*show)(char *,char*);
};
void show(char *a1,char * a2)
{
cout<<a1<<"-"<<a2<<endl;
}
int main()
{
struct full_name loki;
loki.fname="Mohit";
loki.lname="Dabas";
loki.show=show;
loki.show(loki.fname,loki.lname);
return 0;
}
In C, structures are allowed to contain on data values and not the function pointers. Not allowed in C. but the following works literally fine when checked with gcc.
enter code here
#include <stdio.h>
struct st_func_ptr{
int data;
int (*callback) ();
};
int cb(){
printf(" Inside the call back \n");
return 0;
}
int main() {
struct st_func_ptr sfp = {10, cb};
printf("return value = %d \n",sfp.callback());
printf(" Inside main\n");
return 0;
}
So, am confused ...
It's all right.
In the linux kernel code,you will find many structures contain functions.
such as:
/*
* The type of device, "struct device" is embedded in. A class
* or bus can contain devices of different types
* like "partitions" and "disks", "mouse" and "event".
* This identifies the device type and carries type-specific
* information, equivalent to the kobj_type of a kobject.
* If "name" is specified, the uevent will contain it in
* the DEVTYPE variable.
*/
struct device_type {
const char *name;
struct attribute_group **groups;
int (*uevent)(struct device *dev, struct kobj_uevent_env *env);
void (*release)(struct device *dev);
int (*suspend)(struct device * dev, pm_message_t state);
int (*resume)(struct device * dev);
};
Yes its possible to declare a function and the function definition is not allowed and that should be the function pointer.
Its based on C99 tagged structure.
Lokesh V
They can, but there is no inherent advantage in usual C programming.
In C, all functions are in the global space anyway, so you get no information hiding by tucking them in a function. paxdiablo 's example is a way to organize functions into a struct, but you must see has to dereference each one anyway to use it.
The standard organizational structure of C is the File, with
the interfaces in the header and the implementations in the source.
That is how libc is done and that is how almost all C libraries are done.
Moder C compilers allow you to define and implement functions in the same source file, and even implement static functions in header files. This unfortunately leads to some confusion as to what goes where, and you can get unusual solutions like cramming functions into structs, source-only programs with no headers, etc.
You lose the advantage of separating interface from implementation that way.
I've been reading about OOP in C but I never liked how you can't have private data members like you can in C++. But then it came to my mind that you could create 2 structures. One is defined in the header file and the other is defined in the source file.
// =========================================
// in somestruct.h
typedef struct {
int _public_member;
} SomeStruct;
// =========================================
// in somestruct.c
#include "somestruct.h"
typedef struct {
int _public_member;
int _private_member;
} SomeStructSource;
SomeStruct *SomeStruct_Create()
{
SomeStructSource *p = (SomeStructSource *)malloc(sizeof(SomeStructSource));
p->_private_member = 42;
return (SomeStruct *)p;
}
From here you can just cast one structure to the other.
Is this considered bad practice? Or is it done often?
sizeof(SomeStruct) != sizeof(SomeStructSource). This will cause someone to find you and murder you someday.
Personally, I'd more like this:
typedef struct {
int _public_member;
/*I know you wont listen, but don't ever touch this member.*/
int _private_member;
} SomeStructSource;
It's C after all, if people want to screw up, they should be allowed to - no need to hide stuff, except:
If what you need is to keep the ABI/API compatible, there's 2 approaches that's more common from what I've seen.
Don't give your clients access to the struct, give them an opaque handle (a void* with a pretty name), provide init/destroy and accessor functions for everything. This makes sure you can change
the structure without even recompiling the clients if you're writing a library.
provide an opaque handle as part of your struct, which you can allocate however you like. This approach is even used in C++ to provide ABI compatibility.
e.g
struct SomeStruct {
int member;
void* internals; //allocate this to your private struct
};
You almost have it, but haven't gone far enough.
In the header:
struct SomeStruct;
typedef struct SomeStruct *SomeThing;
SomeThing create_some_thing();
destroy_some_thing(SomeThing thing);
int get_public_member_some_thing(SomeThing thing);
void set_public_member_some_thing(SomeThing thing, int value);
In the .c:
struct SomeStruct {
int public_member;
int private_member;
};
SomeThing create_some_thing()
{
SomeThing thing = malloc(sizeof(*thing));
thing->public_member = 0;
thing->private_member = 0;
return thing;
}
... etc ...
The point is, here now consumers have no knowledge of the internals of SomeStruct, and you can change it with impunity, adding and removing members at will, even without consumers needing to recompile. They also can't "accidentally" munge members directly, or allocate SomeStruct on the stack. This of course can also be viewed as a disadvantage.
I do not recommend using the public struct pattern. The correct design pattern, for OOP in C, is to provide functions to access every data, never allowing public access to data. The class data should be declared at the source, in order to be private, and be referenced in a forward manner, where Create and Destroy does allocation and free of the data. In a such way the public/private dilemma won't exist any more.
/*********** header.h ***********/
typedef struct sModuleData module_t'
module_t *Module_Create();
void Module_Destroy(module_t *);
/* Only getters and Setters to access data */
void Module_SetSomething(module_t *);
void Module_GetSomething(module_t *);
/*********** source.c ***********/
struct sModuleData {
/* private data */
};
module_t *Module_Create()
{
module_t *inst = (module_t *)malloc(sizeof(struct sModuleData));
/* ... */
return inst;
}
void Module_Destroy(module_t *inst)
{
/* ... */
free(inst);
}
/* Other functions implementation */
In the other side, if you do not want to use Malloc/Free (which can be unnecessary overhead for some situations) I suggest you hide the struct in a private file. Private members will be accessible, but that on user's stake.
/*********** privateTypes.h ***********/
/* All private, non forward, datatypes goes here */
struct sModuleData {
/* private data */
};
/*********** header.h ***********/
#include "privateTypes.h"
typedef struct sModuleData module_t;
void Module_Init(module_t *);
void Module_Deinit(module_t *);
/* Only getters and Setters to access data */
void Module_SetSomething(module_t *);
void Module_GetSomething(module_t *);
/*********** source.c ***********/
void Module_Init(module_t *inst)
{
/* perform initialization on the instance */
}
void Module_Deinit(module_t *inst)
{
/* perform deinitialization on the instance */
}
/*********** main.c ***********/
int main()
{
module_t mod_instance;
module_Init(&mod_instance);
/* and so on */
}
Never do that. If your API supports anything that takes SomeStruct as a parameter (which I'm expecting it does) then they could allocate one on a stack and pass it in. You'd get major errors trying to access the private member since the one the compiler allocates for the client class doesn't contain space for it.
The classic way to hide members in a struct is to make it a void*. It's basically a handle/cookie that only your implementation files know about. Pretty much every C library does this for private data.
Something similar to the method you've proposed is indeed used sometimes (eg. see the different varities of struct sockaddr* in the BSD sockets API), but it's almost impossible to use without violating C99's strict aliasing rules.
You can, however, do it safely:
somestruct.h:
struct SomeStructPrivate; /* Opaque type */
typedef struct {
int _public_member;
struct SomeStructPrivate *private;
} SomeStruct;
somestruct.c:
#include "somestruct.h"
struct SomeStructPrivate {
int _member;
};
SomeStruct *SomeStruct_Create()
{
SomeStruct *p = malloc(sizeof *p);
p->private = malloc(sizeof *p->private);
p->private->_member = 0xWHATEVER;
return p;
}
I'd write a hidden structure, and reference it using a pointer in the public structure. For example, your .h could have:
typedef struct {
int a, b;
void *private;
} public_t;
And your .c:
typedef struct {
int c, d;
} private_t;
It obviously doesn't protect against pointer arithmetic, and adds a bit of overhead for allocation/deallocation, but I guess it's beyond the scope of the question.
There are better ways to do this, like using a void * pointer to a private structure in the public struct. The way you are doing it you're fooling the compiler.
Use the following workaround:
#include <stdio.h>
#define C_PRIVATE(T) struct T##private {
#define C_PRIVATE_END } private;
#define C_PRIV(x) ((x).private)
#define C_PRIV_REF(x) (&(x)->private)
struct T {
int a;
C_PRIVATE(T)
int x;
C_PRIVATE_END
};
int main()
{
struct T t;
struct T *tref = &t;
t.a = 1;
C_PRIV(t).x = 2;
printf("t.a = %d\nt.x = %d\n", t.a, C_PRIV(t).x);
tref->a = 3;
C_PRIV_REF(tref)->x = 4;
printf("tref->a = %d\ntref->x = %d\n", tref->a, C_PRIV_REF(tref)->x);
return 0;
}
Result is:
t.a = 1
t.x = 2
tref->a = 3
tref->x = 4
I found that bit-field might be a good solution if you really want to hide something.
struct person {
unsigned long :64;
char *name;
int age;
};
struct wallet {
char *currency;
double balance;
};
The first member of struct person is an unnamed bit-field. used for a 64-bit pointer in this case. It's completely hidden and cannot be accessed by struct variable name.
Because of the first 64-bit in this struct is unused, so we can use it as a private pointer. We can access this member by its memory address instead of variable name.
void init_person(struct person* p, struct wallet* w) {
*(unsigned long *)p = (unsigned long)w;
// now the first 64-bit of person is a pointer of wallet
}
struct wallet* get_wallet(struct person* p) {
return (struct wallet*)*(unsigned long *)p;
}
A small working example, tested on my intel mac:
//
// Created by Rieon Ke on 2020/7/6.
//
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#if __x86_64__ || __LP64__
#define PRIVATE_SET(obj, val) *(unsigned long *) obj = (unsigned long) val;
#define PRIVATE_GET(obj, type) (type)*(unsigned long *) obj;
#define PRIVATE_POINTER unsigned long:64
#else
#define PRIVATE_SET(obj, val) *(unsigned int *) obj = (unsigned int) val;
#define PRIVATE_GET(obj, type) (type)*(unsigned int *) obj;
#define PRIVATE_POINTER unsigned int:32
#endif
struct person {
PRIVATE_POINTER;
char *name;
int age;
};
struct wallet {
char *currency;
double balance;
};
int main() {
struct wallet w;
w.currency = strdup("$$");
w.balance = 99.9;
struct person p;
PRIVATE_SET(&p, &w) //set private member
p.name = strdup("JOHN");
p.age = 18;
struct wallet *pw = PRIVATE_GET(&p, struct wallet*) //get private member
assert(strcmp(pw->currency, "$$") == 0);
assert(pw->balance == 99.9);
free(w.currency);
free(p.name);
return 0;
}
This approach is valid, useful, standard C.
A slightly different approach, used by sockets API, which was defined by BSD Unix, is the style used for struct sockaddr.
My solution would be to provide only the prototype of the internal struct and then declare the definition in the .c file. Very useful to show C interface and use C++ behind.
.h :
struct internal;
struct foo {
int public_field;
struct internal *_internal;
};
.c :
struct internal {
int private_field; // could be a C++ class
};
Note: In that case, the variable have to be a pointer because the compiler is unable to know the size of the internal struct.
Not very private, given that the calling code can cast back to a (SomeStructSource *). Also, what happens when you want to add another public member? You'll have to break binary compatibility.
EDIT: I missed that it was in a .c file, but there really is nothing stopping a client from copying it out, or possibly even #includeing the .c file directly.
Related, though not exactly hiding.
Is to conditionally deprecate members.
Note that this works for GCC/Clang, but MSVC and other compilers can deprecate too,
so its possible to come up with a more portable version.
If you build with fairly strict warnings, or warnings as errors, this at least avoids accidental use.
// =========================================
// in somestruct.h
#ifdef _IS_SOMESTRUCT_C
# if defined(__GNUC__)
# define HIDE_MEMBER __attribute__((deprecated))
# else
# define HIDE_MEMBER /* no hiding! */
# endif
#else
# define HIDE_MEMBER
#endif
typedef struct {
int _public_member;
int _private_member HIDE_MEMBER;
} SomeStruct;
#undef HIDE_MEMBER
// =========================================
// in somestruct.c
#define _IS_SOMESTRUCT_C
#include "somestruct.h"
SomeStruct *SomeStruct_Create()
{
SomeStructSource *p = (SomeStructSource *)malloc(sizeof(SomeStructSource));
p->_private_member = 42;
return (SomeStruct *)p;
}
An anonymous struct can be of use here.
#ifndef MYSTRUCT_H
#define MYSTRUCT_H
typedef struct {
int i;
struct {
int j;
} MYSTRUCT_PRIVATE;
// NOTE: Avoid putting public members after private
int k;
} MyStruct;
void test_mystruct();
#endif
In any file that should have access to the private members, define MYSTRUCT_PRIVATE as an empty token before including this header. In those files, the private members are in an anonymous struct and can be accessed using m.j, but in all other places they can only be accessed using m.MYSTRUCT_PRIVATE.j.
#define MYSTRUCT_PRIVATE
#include "mystruct.h"
void test_mystruct() {
// Can access .j without MYSTRUCT_PRIVATE in both
// initializer and dot operator.
MyStruct m = { .i = 10, .j = 20, .k = 30 };
m.j = 20;
}
#include <stdio.h>
#include "mystruct.h"
int main() {
// You can declare structs and, if you jump through
// a small hoop, access private members
MyStruct m = { .i = 10, .k = 30 };
m.MYSTRUCT_PRIVATE.j = 20;
// This will not work
//MyStruct m2 = { .i = 10, .j = 20, .k = 30 };
// But this WILL work, be careful
MyStruct m3 = { 10, 20, 30 };
test_mystruct();
return 0;
}
I do not recommend putting public members after private members. Initializing a struct without member designators, such as with { 10, 20, 30 } can still initialize private members. If the number of private members changes, this will also silently break all initializers without member designators. It's probably best to always use member designators to avoid this.
You must design your structs, and especially the private members, to be zero initialized since there are no automatic constructors as in C++. As long as the members are initialized to 0 then they won't be left in an invalid state even without an initialization function. Barring a member designator initialization, initializing to simply { 0 } should be designed to be safe.
The only downside I've found is that this does mess with things like debuggers and code completion, they typically don't like it when one type has one set of members in one file, and a different set in another file.
Here's a very organized way to do it using macros. This is how I've seen it used in some of the big projects. I will assume the following:
Header file with the struct
Source file with access to private fields
Source file with no access to private fields (the fields exist but are renamed).
Header file:
// You can put this part in a header file
// and share it between multiple header files in your project
#ifndef ALLOW_PRIVATE_ACCESS
#define PRIVATE(T) private_##T
#else
#define PRIVATE(T) T
#endif
#define PUBLIC(T) T
typedef struct {
int PRIVATE(m1); // private member
int PUBLIC(m2); // public member
} mystruct;
mystruct *mystruct_create(void);
int mystruct_get_m1(mystruct *t);
Source file with access to private fields:
#include <stdlib.h>
#define ALLOW_PRIVATE_ACCESS
#include "mystruct.h"
mystruct *mystruct_create(void) {
mystruct *p = (mystruct *)malloc(sizeof(mystruct));
p->m1 = 42; // works (private)
p->m2 = 34; // works (public)
return (mystruct *)p;
}
int mystruct_get_m1(mystruct *t) {
return t->m1; // works (private)
}
Source file with no access to private fields:
#include <stdio.h>
#include <stdlib.h>
#include "mystruct.h"
int main() {
mystruct *t = mystruct_create();
printf("t->m1 = %d\n", t->m1); // error (private)
printf("t->m1 = %d\n", mystruct_get_m1(t)); // works (using function)
printf("t->m2 = %d\n", t->m2); // works (public)
free(t);
return 0;
}