C - function inside struct
Im trying to assign a function inside a struct
, so far I have this code:
typedef struct client_t client_t, *pno;
struct client_t
{
pid_t pid;
char password[TAM_MAX]; // -> 50 chars
pno next;
pno AddClient()
{
/* code */
}
};
int main()
{
client_t client;
// code ..
client.AddClient();
}
**Error**: *client.h:24:2: error: expected ‘:’, ‘,’, ‘;’, ‘}’ or ‘__attribute__’ before ‘{’ token.*
Which is the correct way to do it ?
It can't be done directly, but you can emulate the same thing using function pointers and explicitly passing the "this" parameter:
typedef struct client_t client_t, *pno;
struct client_t
{
pid_t pid;
char password[TAM_MAX]; // -> 50 chars
pno next;
pno (*AddClient)(client_t *);
};
pno client_t_AddClient(client_t *self) { /* code */ }
int main()
{
client_t client;
client.AddClient = client_t_AddClient; // probably really done in some init fn
//code ..
client.AddClient(&client);
}
It turns out that doing this, however, doesn't really buy you an awful lot. As such, you won't see many C APIs implemented in this style, since you may as well just call your external function and pass the instance.
As others have noted, embedding function pointers directly inside your structure is usually reserved for special purposes, like a callback function.
What you probably want is something more like a virtual method table.
typedef struct client_ops_t client_ops_t;
typedef struct client_t client_t, *pno;
struct client_t {
/* ... */
client_ops_t *ops;
};
struct client_ops_t {
pno (*AddClient)(client_t *);
pno (*RemoveClient)(client_t *);
};
pno AddClient (client_t *client) { return client->ops->AddClient(client); }
pno RemoveClient (client_t *client) { return client->ops->RemoveClient(client); }
Now, adding more operations does not change the size of the client_t
structure. Now, this kind of flexibility is only useful if you need to define many kinds of clients, or want to allow users of your client_t
interface to be able to augment how the operations behave.
This kind of structure does appear in real code. The OpenSSL BIO layer looks similar to this, and also UNIX device driver interfaces have a layer like this.
How about this?
#include <stdio.h>
typedef struct hello {
int (*someFunction)();
} hello;
int foo() {
return 0;
}
hello Hello() {
struct hello aHello;
aHello.someFunction = &foo;
return aHello;
}
int main()
{
struct hello aHello = Hello();
printf("Print hello: %d\n", aHello.someFunction());
return 0;
}
This will only work in C++. Functions in structs are not a feature of C.
Same goes for your client.AddClient(); call ... this is a call for a member function, which is object oriented programming, i.e. C++.
Convert your source to a .cpp file and make sure you are compiling accordingly.
If you need to stick to C, the code below is (sort of) the equivalent:
typedef struct client_t client_t, *pno;
struct client_t
{
pid_t pid;
char password[TAM_MAX]; // -> 50 chars
pno next;
};
pno AddClient(pno *pclient)
{
/* code */
}
int main()
{
client_t client;
//code ..
AddClient(client);
}
You are trying to group code according to struct. C grouping is by file. You put all the functions and internal variables in a header or a header and a object ".o" file compiled from a c source file.
It is not necessary to reinvent object-orientation from scratch for a C program, which is not an object oriented language.
I have seen this before. It is a strange thing. Coders, some of them, have an aversion to passing an object they want to change into a function to change it, even though that is the standard way to do so.
I blame C++, because it hid the fact that the class object is always the first parameter in a member function, but it is hidden. So it looks like it is not passing the object into the function, even though it is.
Client.addClient(Client& c); // addClient first parameter is actually
// "this", a pointer to the Client object.
C is flexible and can take passing things by reference.
A C function often returns only a status byte or int and that is often ignored. In your case a proper form might be
/* add client to struct, return 0 on success */
err = addClient( container_t cnt, client_t c);
if ( err != 0 )
{
fprintf(stderr, "could not add client (%d) \n", err );
}
addClient would be in Client.h or Client.c