For the current project I cannot use C++ (unfortunately), only pure C, and Im having the following problem:
I got 3 distinctive struct that need to call the same function name, and I feel its more elegant the way it is below instead of creating 3 different function for the different type, like I feel its easier to maintain. How can I get the pointer that call the function? Basically what I'm trying to reproduce is basically similar as "this" in C++ or self (in Obj-C), is there anyway I can do that in plain C?
[ test.h ]
enum
{
TYPE_A = 0,
TYPE_B = 1,
TYPE_C = 2
};
typedef struct
{
char type;
void ( *GetType )( void );
// Some other data different than the other struct
}A;
typedef struct
{
char type;
void ( *GetType )( void );
/* Some other data different than the other struct */
}B;
typedef struct
{
char type;
void ( *GetType )( void );
// Some other data different than the other struct
} C;
A *create_a( void );
B *create_b( void );
C *create_c( void );
void GetType( void );
[ test.c ]
A *create_a( void )
{
A *a = ( A * ) calloc( 1, sizeof( A ) );
a->type = TYPE_A;
a->GetType = GetType;
return a;
}
B *create_b( void )
{
B *b = ( B * ) calloc( 1, sizeof( B ) );
b->type = TYPE_B;
b->GetType = GetType;
return b;
}
C *create_c( void )
{
C *c = ( C * ) calloc( 1, sizeof( C ) );
c->type = TYPE_C;
c->GetType = GetType;
return c;
}
void GetType( void )
{
printf("How to get the pointer that call this function to retrieve the type?");
}
[ main.c ]
int main (int argc, const char * argv[])
{
A *a = create_a();
B *b = create_b();
C *c = create_c();
a->GetType();
b->GetType();
c->GetType();
return 0;
}
The traditional way to do this kind of thing (eg in the UNIX kernel) is by using a #define for syntactic sugar:
#define GET_TYPE(X) ((X)->GetType((X)))
Of course if there are more arguments it passes those as well. The function pointers are usually collected in one static "ops" structure which is assigned on creation (instead of every individual function pointer). Each ops vector has a corresponding collection of #defines.
Pass this as a normal parameter (first, to be conventional):
void GetType(void *this);
...
GetType(a); // instead of C++-style a->GetType
It'd be better to have some "base class" (including "int type" field), in this case pointer will be "struct Base *this", not a "void *this").
Personally I always go this way. You can add prefix for a functions of some "class" (for example, Cl1_GetType). This is the way of OO-programming in C. "Real virtual functions" through function pointers could also be used, but it's not such common case.
"this" should be given as a parameter to GetType(). That's how object methods are actually implemented under the hood. Moreover, since GetType should be able to interact with all kind of struct - the structs should have a similar "base class". for example:
#include "stdio.h"
typedef enum
{
TYPE_A = 0,
TYPE_B = 1,
TYPE_C = 2
} my_class_type;
typedef struct
{
char type;
my_class_type ( *GetType )( void* );
}my_base;
my_class_type my_base_GetType( void* my_base_ptr)
{
return ((my_base*)my_base_ptr)->type;
}
typedef struct
{
my_base base;
// Some other data different than the other struct
}A;
typedef struct
{
my_base base;
/* Some other data different than the other struct */
}B;
typedef struct
{
my_base base;
// Some other data different than the other struct
}C;
A *create_a( void )
{
A *a = ( A * ) calloc( 1, sizeof( A ) );
a->base.type = TYPE_A;
a->base.GetType = my_base_GetType;
return a;
}
B *create_b( void )
{
B *b = ( B * ) calloc( 1, sizeof( B ) );
b->base.type = TYPE_B;
b->base.GetType = my_base_GetType;
return b;
}
C *create_c( void )
{
C *c = ( C * ) calloc( 1, sizeof( C ) );
c->base.type = TYPE_C;
c->base.GetType = my_base_GetType;
return c;
}
int main(int argc, char* argv[])
{
A *a = create_a();
B *b = create_b();
C *c = create_c();
printf("%d\n",a->base.GetType(a));
printf("%d\n",b->base.GetType(b));
printf("%d\n",c->base.GetType(c));
return 0;
}
This example implements inheritance and polymorphism. All structs share the same base core and if you want to override GetType() you just change the pointer in base. you can hold a pointer to my_base and dynamically resolve the type.
From what i understood of your question is: "You just want to obtain the value of the type field in the structure in GetType function". Is this right? If yes, you can do it this way:
enum
{
TYPE_A = 0,
TYPE_B = 1,
TYPE_C = 2
};
typedef struct
{
char type;
// Some other data different than the other struct
}A;
typedef struct
{
char type;
/* Some other data different than the other struct */
}B;
typedef struct
{
char type;
// Some other data different than the other struct
} C;
A *create_a( void );
B *create_b( void );
C *create_c( void );
void GetType( void * );
[test.c]
A *create_a( void )
{
A *a = ( A * ) calloc( 1, sizeof( A ) );
a->type = TYPE_A;
return a;
}
B *create_b( void )
{
B *b = ( B * ) calloc( 1, sizeof( B ) );
b->type = TYPE_B;
return b;
}
C *create_c( void )
{
C *c = ( C * ) calloc( 1, sizeof( C ) );
c->type = TYPE_C;
return c;
}
#define GetType(x) (x->type)
[main.c]
int main (int argc, const char * argv[])
{
A *a = create_a();
B *b = create_b();
C *c = create_c();
GetType(a);
GetType(b);
GetType(c);
return 0;
}
Hope this answers your question.
Related
I'm trying to make a small library for particle management that allows to "expand" struct with user's data (texture, animation frames, etc). The library would know only the size of the expanded struct.
How do I iterate through the array of unknown struct types but known size of a struct?
typedef struct{
int type;
}Base;
typedef struct{
Base base;
int value;
}inherited;
int main(){
size_t size = sizeof(inherited);
int count = 10;
void *b = malloc(size * count);
for (int i = 0; i < count; i++){
// iterate based on known size & send to callback
callback( &( (size)b )[i] );
}
free(b);
return 0;
}
I assume the code that does the malloc and calls callback doesn't know anything about the type of the object, only its size.
#include <stdlib.h>
void *alloc_and_init(size_t nmemb, size_t size, void (*callback)(void *))
{
void *b = calloc(nmemb, size);
if (b)
{
char *p = b;
for (size_t i = 0; i < nmemb; i++)
{
callback(p);
p += size;
}
}
return b;
}
typedef struct{
int type;
}Base;
typedef struct{
Base base;
int value;
}inherited;
void init_inherited(void *p)
{
inherited *obj = p;
/* do initialization of obj->* here */
}
int main(void)
{
int objcount = 10;
inherited *objarr;
objarr = alloc_and_init(objcount, sizeof(*objarr),
init_inherited);
/* ... */
free(objarr);
}
for( inherited *p = b, *e = p + count; p < e; p++ ){
callback(p);
}
char *b = malloc(size * count);
for (int i = 0; i < count; i++){
// iterate based on known size & send to callback
callback( b + i * size );
}
Polymorphism in C is always rather clunky. Basically you have to construct a "vtable" manually. The naive, simplified version below lets each object have its own function pointer. You'll end up with something rather contrived like this:
#include <stdio.h>
#include <stdlib.h>
typedef struct base_t base_t;
typedef void callback_t (const base_t* arg);
struct base_t
{
int type;
callback_t* callback;
};
typedef struct
{
base_t base;
int value;
} inherited_t;
void callback_base (const base_t* arg)
{
puts(__func__);
}
void callback_inherited (const base_t* arg)
{
const inherited_t* iarg = (const inherited_t*)arg;
printf("%s value: %d\n", __func__, iarg->value);
}
int main (void)
{
// allocate memory
base_t* array [3] =
{
[0] = malloc(sizeof(inherited_t)),
[1] = malloc(sizeof(base_t)),
[2] = malloc(sizeof(inherited_t)),
};
// initialize objects
*(inherited_t*)array[0] = (inherited_t){ .base.callback=callback_inherited, .value = 123 };
*(array[1]) = (base_t){ .callback=callback_base };
*(inherited_t*)array[2] = (inherited_t){ .base.callback=callback_inherited, .value = 456 };
for (int i = 0; i < 3; i++)
{
array[i]->callback(array[i]); // now we get polymorphism here
}
}
A more professional version involves writing a translation unit (.h + .c) per "class" and then combine allocation with initialization in the "constructor". It would be implemented with opaque type, see How to do private encapsulation in C? Inside the constructor, set the vtable corresponding to the type of object allocated.
I'd also boldly claim that any OO solution using void* arguments has some design flaw. The interface should be using the base class pointer. Void pointers are dangerous.
Here is a 2D array of char*, storing for example different strings in different languages :
typedef enum
{
FRENCH,
ENGLISH,
GERMAN,
LANGUAGES_COUNT
} languages_t;
typedef enum
{
HELLO,
THANK_YOU,
WORDS_COUNT
} words_t;
char *text_tab[WORDS_COUNT][LANGUAGES_COUNT] =
{
{"bonjour", "hello", "guten tag"},
{"merci", "thank you", "danke"}
};
No trouble to access it :
int main()
{
printf("%s\n", text_tab[HELLO][ENGLISH]);
printf("%s\n", text_tab[THANK_YOU][FRENCH]);
printf("%s\n", text_tab[HELLO][GERMAN]);
return 0;
}
Now, I don't want to access text_tab directly, but through a structure :
typedef struct
{
int a;
char ***txt; // here is not working
} test_t;
test_t mystruct = {5, text_tab};
The idea is to access text_tab this way :
printf("%s\n", mystruct.txt[BONJOUR][ANGLAIS]);
printf("%s\n", mystruct.txt[MERCI][FRANCAIS]);
printf("%s\n", mystruct.txt[BONJOUR][ALLEMAND]);
How to declare the field "txt" in the structure ?
I only use static allocation and I don't want to copy the content of "text_tab" in "txt", juste use a pointer.
Thanks.
This array
char *text_tab[WORDS_COUNT][LANGUAGES_COUNT] =
{
{"bonjour", "hello", "guten tag"},
{"merci", "thank you", "danke"}
};
has the type char * [WORDS_COUNT][LANGUAGES_COUNT].
So a pointer to elements of the array has the type char * ( * )[LANGUAGES_COUNT]
Hence the structure can be declared like
typedef struct
{
size_t a;
char * ( *txt )[LANGUAGES_COUNT];
} test_t;
And in main you can declare an object of the structure type like
test_t mystruct = { sizeof( text_tab ) / sizeof( *text_tab ), text_tab };
Here is a demonstrative program.
#include <stdio.h>
#define WORDS_COUNT 2
#define LANGUAGES_COUNT 3
typedef struct
{
size_t a;
char * ( *txt )[LANGUAGES_COUNT];
} test_t;
int main(void)
{
char *text_tab[WORDS_COUNT][LANGUAGES_COUNT] =
{
{"bonjour", "hello", "guten tag"},
{"merci", "thank you", "danke"}
};
test_t mystruct = { sizeof( text_tab ) / sizeof( *text_tab ), text_tab };
for ( size_t i = 0; i < mystruct.a; i++ )
{
for ( size_t j = 0; j < sizeof( *mystruct.txt ) / sizeof( **mystruct.txt ); j++ )
{
printf( "%s ", mystruct.txt[i][j] );
}
putchar( '\n' );
}
return 0;
}
The program output is
bonjour hello guten tag
merci thank you danke
Many Kernel modules seem to opt for the following struct initialization style;
struct file_operations sample_fops = {
.owner = THIS_MODULE,
.read = sample_read,
.write = sample_write,
.ioctl = sample_ioctl,
.open = sample_open,
.release = sample_release,
};
I can wrap my head around when this style is used for primitives and pointer data types but I can't figure out how they work so seamlessly for functions.
When and where are the parameters for this type of initialization created? Is it in the scope of the file or in the scope where the struct is utilized. Can you access the parameters (for instance a pointer to buffer passed as an argument to the write function) or do you have to initialize the struct in a different style in order to be able to do that?
Furthermore, if sample_fops is called multiple times, is it the same struct throughout the file? And where is it kept in the memory during its lifetime? Are the parameters kept in the same place too?
I have not exactly understood your question but this is
struct file_operations sample_fops = {
.owner = THIS_MODULE,
.read = sample_read,
.write = sample_write,
.ioctl = sample_ioctl,
.open = sample_open,
.release = sample_release,
};
a declaration of the object sample_fops that has the type struct file_operations.
It seems that the data members of the structure are declared as pointers to functions and in this declaration function designators as for example sample_open are used to initializa corresponding data members of the structure.
Here is a demonstrative program.
#include <stdio.h>
void f( void )
{
puts( "Hello Yusuf Gürkan Bor" );
}
struct A
{
void ( *hello )( void );
};
int main( void )
{
struct A a = { .hello = f };
a.hello();
}
The program output is
Hello Yusuf Gürkan Bor
This record in the initializarion .fp = f is called a designation initialization.
It uses the name of a data member of a structure that is initialized.
In fact you can equivalently to write
struct A a = { f };
But for a such an initialization you have to keep the order of initializers relative to the order of data members.
Here is another example when a function accepts an argument.
#include <stdio.h>
void f( const char *name )
{
printf( "Hello %s\n", name );
}
struct A
{
void ( *hello )( const char * );
};
int main( void )
{
struct A a = { .hello = f };
a.hello( "Yusuf Gürkan Bor" );
}
Its output is the same as shown above.
The following snippet:
int main ()
{
typedef struct ArrayType
{
int field1;
int field2;
};
struct ArrayType myArray =
{
.field1 = 0,
.field2 = 1,
};
}
is equivalent to
int main ()
{
typedef struct ArrayType
{
int field1;
int field2;
};
ArrayType myArray;
myArray.field1 = 0;
myArray.field2 = 1;
}
if you have a pointer to function, this can work as well.
int function1(int a,int b){ return a+b};
void function2(int c) {};
int main ()
{
typedef struct ArrayType
{
int(*function1)(int,int);
void(*function2)(int);
};
ArrayType myArray;
myArray.function1= thisFunction;
myArray.function2= thatFunction;
}
I want to pass multiple arguments to a function using a void pointer.
void* function(void *params)
{
//casting pointers
//doing something
}
int main()
{
int a = 0
int b = 10;
char x = 'S';
void function(???);
return 0;
}
I know that I have to cast them to a certain variable in my function but I do not know how I can pass my 3 arguments as one void pointer to my function.
I have searched for this problem know quite some time but I could not find anything that would help me.
You could do it like this:
struct my_struct
{
int a;
int b;
char x;
}
void * function(void * pv)
{
struct my_strcut * ps = pv; /* Implicitly converting the void-pointer
/* passed in to a pointer to a struct. */
/* Use ps->a, ps->b and ps->x here. */
return ...; /* NULL or any pointer value valid outside this function */
}
Use it like this
int main(void)
{
struct my_struct s = {42, -1, 'A'};
void * pv = function(&s);
}
Following up on the OP's update:
struct my_struct_foo
{
void * pv1;
void * pv2;
}
struct my_struct_bar
{
int a;
int b;
}
void * function(void * pv)
{
struct my_strcut_foo * ps_foo = pv;
struct my_struct_bar * ps_bar = ps_foo->pv1;
/* Use ps_foo->..., ps_bar->... here. */
return ...; /* NULL or any pointer value valid outside this function */
}
Use it like this
int main(void)
{
struct my_struct_bar s_bar = {42, -1};
struct my_struct_foo s_foo = {&s_bar, NULL};
void * pv = function(&s_foo);
}
The void* is used as a pointer to a "generic" type. Hence, you need to create a wrapping type, cast convert to void* to invoke the function, and cast convert back to your type in the function's body.
#include <stdio.h>
struct args { int a, b; char X; };
void function(void *params)
{
struct args *arg = params;
printf("%d\n", arg->b);
}
int main()
{
struct args prm;
prm.a = 0;
prm.b = 10;
prm.X = 'S';
function(&prm);
return 0;
}
I'm trying to cast a struct inside a struct but am running into issues, heres my simplified code:
#include <stdlib.h>
typedef struct {
void *test;
} abc;
typedef struct {
int a;
int b;
} def;
int main()
{
abc *mystruct = malloc(sizeof(abc) + sizeof(def));
mystruct->(def *)test->a = 3;
return 0;
}
the abc struct may have different types of structs in them, so I'd like to cast dynamically, however, this doesn't appear to work. How do I accomplish this in one statement?
Split the allocation in two parts, first:
abc *mystruct = malloc( sizeof(abc) );
But, when you try to do( if test would be properly cast )
mystruct->test->a
test member isn't pointing anywhere, and by dereferencing it you get undefined behavior.
First point it to valid memory
mystruct->test = malloc( sizeof( def ) ) ;
Then you can use it:
( ( def *)mystruct->test )->a = 3;
^ ^
Notice the parenthesis, you are casting the member void which is mystruct->test not just test.
When casting from void* the proper way is to use static_cast in C++:
abc *mystruct = static_cast<abc*>(malloc(sizeof(abc)));
mystruct->test = malloc(sizeof(def));
static_cast<def*>(mystruct->test)->a = 3;
LIVE DEMO
Now as far as it concerns C. First of, I prefer to define init and finit functions for my structs:
struct abc*
abc_init(int sz) {
struct abc *out = (abc*) malloc(sizeof(abc));
out->test = malloc(sz);
return out;
}
void
abc_finit(struct abc *in) {
if(in) {
if(in->test) free(in->test);
free(in);
}
}
Notice that allocation of struct abc is done in two steps first the memory for struct abc and then for member test.
Now the casting is done like:
((def*)(mystruct->test))->a = 3;
LIVE DEMO
More commonly you would use a union for this sort of thing:
typedef union {
struct {
int a;
int b;
} def;
/* ..other variants you might want */
} abc;
int main() {
abc *mystruct = malloc(sizeof(abc));
mystruct->def.a = 3;
/* do stuff with it */
Try the following
#include <stdlib.h>
#include <stdio.h>
typedef struct {
void *test;
} abc;
typedef struct {
int a;
int b;
} def;
int main()
{
abc *mystruct = malloc( sizeof( abc ) );
if ( mystruct )
{
mystruct->test = malloc( sizeof( def ) );
if ( mystruct->test )
{
( ( def * )mystruct->test )->a = 3;
printf( "%d\n", ( ( def * )mystruct->test )->a );
}
}
if ( mystruct ) free ( mystruct->test );
free( mystruct );
return 0;
}
The output will be
3
(Corrected) ((def *)mystruct->test)->a = 3;
type cast operator has less precedence than -> operator
Here is the reference