C - function inside struct

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.


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;
} 

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.

Tags:

C

Function

Struct