Search code examples
c++cwrapperencapsulationdoubly-linked-list

How to Make a C++ Wrapper for a C Linked List


I've implemented a linked list in C with many functions to help ease its manipulation.
I don't want to port this functionality to C++ so I'm trying to create a simple Wrapper Class that calls the original functions internally, and manipulates the C linked list internally as well.

For most of the functionality, the wrapper code works well. There is one problem, however. The C linked list structure has pointers to the next and the previous C linked list structures, and I want to be able to get the C++ equivalent class pointers instead ..

How can I do that ?

E.x: There is a C function that gets the linked list in the chain at an index. The Original function would do something like this:

struct _linkedlist *LinkedList_get(struct _linkedlist * list, const unsigned long index)
{ /* Gets the index'th linked list in the chain as a pointer */
    if ((list) == NULL) return NULL;
    if (index >= LinkedList_get_depth(list))
        return NULL;
    for(unsigned int i = 0; i < index; list = list->next, ++i);
    return list;
}

The function clearly returns a pointer to the linked list C struct. What I want to do is get a pointer to the C++ linked list wrapper object.

The whole purpose of this is that I can make an object oriented wrapper (the C++ interface) around a purely functional interface (the C interface) without altering the original source (the C version).


Solution

  • You've mentioned in comments that your C linked list stores an arbitrary value type (as void*). Therefore, it should be fairly trivial for the C++ wrapper to store extra information in that value type. This extra information could be the pointer to the corresponding C++ wrapper.

    You haven't shown your code, so I will just show the idea in a generic fashion:

    // This is the original C interface
    struct C_Node;
    
    void* c_getValue(struct C_Node *node);
    
    struct C_Node* c_insertAfter(struct C_Node *node, void *value);
    
    
    // This is the C++ wrapper
    template <class T>
    class Node
    {
      C_Node *cNode;
    
      typedef std::pair<T, Node*> ProxyValueType;
    
      explicit Node(C_Node *cNode) : cNode(cNode)
      {
        static_cast<ProxyValueType*>(c_getValue(cNode))->second = this;
      }
    
    public:
      T& getValue() const
      { return static_cast<ProxyValueType*>(c_getValue(cNode))->first; }
    
      Node* insertAfter(T value)
      {
        ProxyValueType *proxy = new ProxyValueType(T, nullptr);
        C_Node *newNode = c_insertAfter(cNode, proxy);
        return new Node(newNode);
      }
    };
    

    Of course, the above as written is bad C++, as it uses owning raw pointers etc. Treat it as a demonstration of the idea, not as pastable code.