ADT(abstract data type) in C

On 2017/07/30 at 21:30

When tracing the code of libnetfilter_conntrack libray, I found the use of abstract data type implementation in C is very interesting and elegant. Its OOP behavior is the same as the following C++ code:

class nf_conntrack {
    /* some public method...*/
    void set_attr(const enum nf_conntrack_attr type, void* value);
    void* get_attr(const enum nf_conntrack_attr type);
    int compare(const nf_conntrack *other);
    /* blah blah... */
    struct __nfct_tuple repl;
    struct __nfct_tuple master;
    uint32_t    timeout;
    uint32_t    mark;
    /* some other private field */

It restrict users from using nf_conntrack's private field and only allow them using its public member function. The library did it by forward declaring the nf_conntrack and its public function in libnetfilter_conntrack/libnetfiter_conntrack.h and hide the private internal members in internal/internal.h and internal/object.h


/* forward declaring nf_conntrack */
struct nf_conntrack;

extern struct nf_conntrack *nfct_new(void);
extern void nfct_destroy(struct nf_conntrack *ct);

/* setter */
extern void nfct_set_attr(struct nf_conntrack *ct,
              const enum nf_conntrack_attr type,
              const void *value);

/* getter */
extern const void *nfct_get_attr(const struct nf_conntrack *ct,
                 const enum nf_conntrack_attr type);


/* real nf_conntrack definition */

struct nf_conntrack {
    struct nfct_tuple_head  head;
    struct __nfct_tuple repl;
    struct __nfct_tuple master;

    uint32_t    timeout;
    uint32_t    mark;
    uint32_t    secmark;
    uint32_t    status;
    uint32_t    use;
    uint32_t    id;
    uint16_t    zone;
    /* blah blah... */

In conntrack/api.c, the api implementation include internal/internal.h directly. However for users using this library, they can only use the public methods exposed by libnetfilter_conntrack.h.